Entwickler-Ecke
Windows API - Kernel Hooks
Flamefire - Sa 31.10.09 14:24
Titel: Kernel Hooks
Hi,
nachdem ich mich seit längeren mit "normalen" Hooks beschäftigt habe, bin ich vor einer Weile auf Kernel Hooks gestoßen.
Speziell ging es darum, dass ein Kernel Hook (ich vermute zumindest, dass es einer ist) mir dadurch aufgefallen ist, dass er u.a. WriteProcessMemory verhindert, mit dem ich meinen Hook/Patch integrieren wollte. (Geht darum, die Sprache eines Programms zu verändern, was leider nicht wirklich vorgesehen ist)
Ok nachdem ich ne Weile gesucht und nichts gefunden habe, was mir da weiterhilft, habe ich es aufgegeben.
Jetzt kam aber in der Uni u.a. Kernel Mode, Ring0... dran
Da habe ich mich wieder an mein Problem erinnert und mich gewundert, was da los ist.
Kernel Mode i.A. ist dafür da, damit nicht jeder Prozess beliebig was an anderen Prozessen, OS-Fkt u.ä. machen kann. Wenn es aber so einfach ist, in den KernelMode zu kommen, INTx BP zu hooken und auf eigene Funktionen umzuleiten, wodurch man unbeschränkten (KernelMode) Zugriff hat, was bringt der dann?
Dann noch was produktives:
Wie lassen sich Kernel Hooks erkennen und vl beseitigen?
Kann mir jemand etwas zu lesen oder ein Tutorial zu Kernel Hooks empfehlen, wie das mit dem kernel genau funktioniert?
Soweit ich das verstanden habe, wäre ein Ablauf so:
Bsp: OpenProcess()
UserMode:
1)Parameter vorbereiten, INT auslösen
-->Kernel Mode
2)Stack prüfen, feststellen was es für eine Funktion ist, die aufgerufen werden soll
und NTOpenProcess aufrufen (OS-Fkt)
3) Rückkehr in den UserMode
Wenn ich jz also verhindern wöllte, dass jemand was mit meinem Prozess macht, hooke ich NTOpenProcess und gucke ob die PID mein ist. Wenn ja-->return -1
oder ist NTOpenProcess noch im UserMode eine OS-Fkt, die dann nen INT auslöst, wo dann die eigendlich Behandlung gemacht wird?
uall@ogc - Sa 31.10.09 15:24
Der Ablauf ist wie folgt (wenn ich mich jetzt nicht ganz irre, ist schon 2 Jahre her wo ich damit mal was gemacht habe):
kernel32.OpenProcess -> ntdll.NtOpenProcess -> sysenter/syscall/int (je nach Prozessor und Betriebssystem) [wechsel user -> kernelmode] -> Lookup in der SSDT -> win32k.NtOpenProcess -> IRET
"Normalerweise" hat man nur mit nem Teiber Zugriff auf kernelmode und Treiber können "normalerweise" nur vom Admin geladen werden. D.h. Ein Virus etc. kann die Funktionen nciht hooken weil der erst gar net in den kernel mode kommt. NtOpenProcess/writeProceessMemory etc. wird eigentlich von jedem AntiVirus Programm gehookt um das Beenden des AV zu unterbinden und z.B. bei einem NtCreateFile
aufruf wird die Datei gescannt.
In meinen HookUnits ist ein Ring0 hook eingebaut für Delphi ohne Treiber (funktioniert aber nur unter 2k/XP) und nicht in einer VM.
http://uall.cheat-project.com/uallCollection/
Edit1:
Mein Fireshield (ebenfals unter dem Link unter Examples) zeigt dir die Hooks an.
Ansonsten empfehle ich dir IceSword.
Für solche Sachen sollte dir
http://www.rootkit.com weiterhelfen, glaub es gibt da auch ein gutes Buch zu (was ich allerdings nie gelesen habe)
Flamefire - Sa 31.10.09 16:29
was ist der unterschied zwischen den beiden ntOpenProcess?
dein fireshield hab ich mir angeguckt. musste zum compilieren n paar units von dir includen und ualldiasmneu rausnehmen, da nicht vorhanden
dann sagt er mir, dass angeblich alle einträge in der SSDT(1) gehookt sind (kann ich kaum glauben)
außerdem bekomme ich n paar fehler im Log:
"Error while initialzing rin0 modules"
"No export name" bei Ntoskrnl
und EProcess ist leer. (abbruch in der zeile: if (not ReadKernelMemory(@myEProcess,Pointer(fs124+EProcessOffset),SizeOf(DWord),False)) then
in uallring0)
Timosch - So 01.11.09 00:01
Moderiert von
Narses: Komplett-Zitat des letzten Beitrags entfernt.
Kann ich nur zustimmen. Hab ich auch; ist ein sehr gutes Buch, wenn man sich mal tiefer mit der Materie befassen will. Der Titel ist recht einseitig und somit etwas irreführend. Das ist vermutlich auch das Buch, von dem uall@ogc gesprochen hat.
uall@ogc - So 01.11.09 15:26
Ja das meinte ich, außerdem sollte das Buch
Windows 2000 Internals noch ganz gut sein. Ist von Mark Russinovich (derjenige der bei MS die Sysinternals Programme programmiert).
Soviel ich weiß gobts noch ein 2. Buch von Greg Houghland (oder wie der heißt von Rootkits) heißt irgendwie GameHacking. Soll auch gut sein.
Hab die alle zwar nie gelesen aber nut gutes von gehört :)
Ich muß ehrlich sagen, dass ich Fireshield lange nicht mehr benutzt habe (gab sogar mal ne 2. Version) und hab wegem Zocken nur Vista drauf, kann dir also da im Moment nicht weiterhelfen.
Flamefire - So 01.11.09 18:33
ok ich werde mal zusehen, wo ich das herbekomme. klingt zumindest sehr intressant
als beispiel werde ich mal versuchen, mittels kernel hooks einen prozess nicht öffnen zu lassen (Openprocess immer -1) und das dann mit einem anderen programm umgehen.
denke wird ne gute übung sein...freu mich schon auf die BSODs xD
aber erstmal n bissl was lesen
Edit: habs bekommen :-)
anfang ist schon mal gut geschrieben. mal sehn wies weitergeht
Edit2:
Mal ne Frage an uall: woher hast du deine kenntnisse über den kernel? wie hast du deine hooks gemacht? mit welchem debugger kommt man in den Kernel (sysenter) rein?
Edit3:
Ich hab das hier gefunden:
http://rootkit.com/blog.php?newsid = 958 (sry der link geht nicht direkt)
sehr intressent. zwar kein Kerneldebugger, aber er erkennt kernel Hooks, kann den kernel dasm und die hooks rückgängig machen.
Würde mich ja mal intressieren, wie der den hook erkennt und sogar rückgängig macht. *zu uall schiel*
Flamefire - Mi 04.11.09 11:18
ok also das buch ist echt relativ gut. auch wenn der code dazu mehr erklärt werden könnte. geht aber
dann aber ne frage:
ist es mit delphi SINNVOLL möglich treiber zu programmieren?
hab das DDDK 0.0.4 gefunden, aber da fehlen die meisten funktionen.
samples waren auch dazu. z.b. eins, dass zwOpenProcess hookt. funktioniert auch, nur leider fehlen wirklich viele funktionen und deklarationen. z.b. PSCurrentProcessId und mir ist es nicht gelungen, diese funktion einzubinden und auszuführen (BSOD)
Aber das WDK ist 2GB groß...Ohne VS oder andere IDE
desweiteren zum verständnis: mit uAllRing0 kann man mit einem UserMode Programm funktionen im KernelMode ausführen.
SSDT hooks dürften da aber ziemlich gefährlich sein. wenn das programm abstürzt oder unsauber beendet wird, zeigt der hook auf falschen speicher und man kriegt nen BS
Darum 3 Fragen dazu:
1) Kann man das ändern? Also iwo speicher allozieren, dort funktionen und Daten reinladen und von dort aus den Kernel hooken? Kann man den Code dann auch wieder entfernen, für den fall, dass das Programm abgestürzt ist?
2) Wie ist das überhaupt mit Daten bei nem KernelHook? Könnte ich auf globale Variablen meines Programms zugreifen, dass den SSDT hook gemacht wird?
Wie ist das dort mit den Virtuellen Adressen? woher weiß der SSDT handler, in welchem Kontext er die virtuellen adressen auflösen muss?
3) Hieß es im Buch, dass der Speicher eines Prozesses zum Teil auch KernelMode speicher ist. D.h. man kann in den KernelMode speicher schreiben, und die Adresse entspricht dann aber einer UserMode Adresse. Wie ist die Umrechnung?
uall@ogc - Mi 04.11.09 20:09
Treiber in Delphi sind nicht wirklich sinnvoll, rin theoretisch geht es (siehe DDDK) aber wie du sicherlich siehst musst du die meisten Funktionen selbst Deklarieren.
Wenn du Informatik studierst solltest du ja VS über MSDNAA bekommen, 2GB ist ja net nur der Source.
uallRing0 schreibt die Exe in den Kernelmode, so dass die gehookten Funktionen im Kernel sind und auch nach dem beenden des Programms funktionieren. Speicher wird dorch auch reserviert (weiß gerade den Namen der Funktion nicht). Zum reservieres des Speichers wird ein Teil zuerst ein Teil der win32k.sys überschrieben mit einem LoaderCode überschreiben (natürlich vorher gesichert). Dann wird ein Hook von zwOpenProcess erstellt (in der SSDT) der auf diesen Speicher verweist. Im Anschluss wird Openprocess mit einem speziellen Parameter aufgerufen, den der Loadercode abfängt (und somit weiß das es sich um den uallProcess handelt) und springt in den Code der EXE (d.h. der Code wird im Ring0 ausgeführt). Deser übernimmt die eigentlich Allozierung von Kernel Speicher und kopiert die Exe dorthin. Zm Schluss wird der OpenProcess hook entfernt und die win32k.sys komplett wieder hergestellt. Es ist ein wirlkicher Hack, den ich mir damals dafür ausgedacht habe es soll auch nur demonstrieren, dass man Code im Kernel ausführen kann.
Ein Umrechnung von Virtuellem und Physischen Speicher solte ebenfalls in uallRing0 vorhanden sein, auch im Kernel kannst du mit PSCurrentProcessID z.B. die akutelle ID von dem Prozess rausfinden der die zw* Funktion auferufen hat. Mit der EProcess Liste (ebenfalls in uallRin0 genauer erklärt) kannst du dann auf die einzelen Handles usw. zugreifen und sogar deinen Prozess daraus ausklinken (somit nicht mehr sichtbar). uallRing0 liest außerdem die ShadowTabelle aus (u.a. verweisen da die user32.dll und gdi32.dll Funktionen darauf). D.h. du kannst z.B. BitBlt hooken und verändern bzw. ExtEscape (opengl).
Flamefire - Mi 04.11.09 21:40
aber muss man nicht schon im kernel mode sein, um die win32k.sys und die SSDT zu überschreiben?
nja ich denke das beste bleibt, mit VS treiber zu erstellen.
BTW: es gibt ja auch den borland c++ builder
eignet sich der auch?
wie verwende ich das WDK mit der IDE?
Timosch - Mi 04.11.09 21:49
Flamefire hat folgendes geschrieben : |
nja ich denke das beste bleibt, mit VS treiber zu erstellen.
BTW: es gibt ja auch den borland c++ builder
eignet sich der auch?
|
Zum Treiber programmieren verwendet man das DDK von Microsoft.
uall@ogc - Do 05.11.09 20:32
Den Trick den ich benutze ist, dass man auf den kompletten Arbeitspeicher auch per CreateFileA / MemoryMapping zugreifen kann (\\PhysicalMemory). Dort kann man dann alles abändern (u.a. auch die win32k.sys). DIe muss man nur im Speicher finden.
Flamefire - Do 05.11.09 21:11
jo danke uall
habs gesehn.
hab mir heute mal die ganze unit angeguckt und für D2009 umgeschrieben (WideStrings >.<)
funktioniert auch soweit. gute idee mit dem memory scan für nach den dlls/treibern ;-)
nur aus irgendeinem grund funktioniert der scan nach den seitentabellen nicht (mehr)
findet sie nicht.
aber das ist für meine zwecke erst mal unwichtig.
de fakto kann ich mit dieser unit kernelspeicher allozieren, meinen code da rein kopieren und hooks dahin schreiben...brauch man ja keine treiber mehr ;-)
werd mir das mit den treiber trptzdem ma angucken. wie richtie ich VS für das WDK ein?
Flamefire - Fr 06.11.09 20:59
sry uall, muss speziell dich nochmal mit ner frage belästigen:
zur funktionsweise von EnterRing0viaSSDT
was ich daran sehe ist:
-funktionspointer in globale variable
-callbackfunktion in den pe-header der kerneldatei im speicher laden
-adresse und originalwert aus der ssdt in der funktion umändern
-funktion als nicht auslagerbar markieren
-ssdt eintrag ändern
-funktion im kernel aufrufen-->callback
-zurückschreiben des originalwertes und aufrufen der funktion (im kernelmodus)
-prüfen, ob alles ok und wiederherstellen des pe-headers
damit ist die funktion an sich doch aber nicht im kernelspeicher, sondern immernoch im process-speicher.
demzufolge ist die adresse der funktion eine virtuelle des prozesses.
warum funktioniert das dann? wie kann der im kernelmodus die virtuelle adresse auflösen? (besonders die der globalen variablen (die die funktion möglicherweise benutzt), die könnten ja sogar ausgelagert werden, oder?)
und selbst wenn der context im kernelmodus für diesen aufruf der des prozesses ist, würde das nicht abstürzen, wenn ein andrer prozess zufällig grade da die funktion aufruft (auch wenn unwahrscheinlich)?
dann die frage: gibts ne doku zu den funktionen?
bei der loadasdriver sehe ich, dass es eine dll,exe,sys in den kernelspeicher lädt (mit korrekten relocs)
nur, wie benutze ich das, und wie benutze ich dann die dll?
wäre es z.b. möglich eine dll zu schreiben, damit zu laden, dann eine funktion der dll aufzurufen, die dann andre funktionen hookt?
die dll müsste ja dann im kernelmodus laufen, oder kann die nur im kernelmodus aufgerufen werden (wodurch sie dann im kernelmodus läuft)?
was müsste ich da beachten (winapi calls werden ja dort dann nicht funktionieren, oder?)
PS: in dem zusammenhang bitte auch
beachten [
http://www.delphi-forum.de/viewtopic.php?p=583850#583850]
uall@ogc - Sa 07.11.09 13:03
Hi, wie gesagt ist lange her, ich hab mir gerade den code mal angeschaut:
EnterRing0viaSSDT
führt eine lokale Funktion aus (mit Virtuellen Adressen). Das Funktioniert deshalb, da der eigene Code in den Kernel springt. Dies wird über ProcessPriorität gemacht und über den Check über
Result := OpenProcess($1337, False, $1337) = $1337;
Wie erwähnt hooke ich OpenProcess in der SSDT, diese springt dann in die win32k.syss (die teilweise überschrieben wurde) dort ist ein check auf die parameter $1337 und nur wenn das stimmt wird die eigentliche Funktion aufgerufen (lokale funktion). Da es im selben Prozess funktioniert es. Im Grunde wird das aber nur verwendet um mittels MmAllocateContiguousMemorySSDT kernelspeicher zu holen. Der wird in LoadAsDriver verwendet um die eigene EXE dann in den Kernelspeicher zu schreiben (mit virtuellen Adressen > 0x80000000, eben Kernelmem). Ich weiß jetzt allerdings nicht ob diese dann direkt aufgelöst werden (sodass der Code dann im jeden Prozess funktioniert). Ist schon zulange her :) Zum ddk hab ich leider keine Ahnung :/
Assarbad - Mi 02.12.09 07:28
Flamefire hat folgendes geschrieben : |
| Kernel Mode i.A. ist dafür da, damit nicht jeder Prozess beliebig was an anderen Prozessen, OS-Fkt u.ä. machen kann. Wenn es aber so einfach ist, in den KernelMode zu kommen, INTx BP zu hooken und auf eigene Funktionen umzuleiten, wodurch man unbeschränkten (KernelMode) Zugriff hat, was bringt der dann? |
Wie definierst Du "einfach"?
Es werden bestimmte Privilegien benötigt um überhaupt Treiber installieren zu können. Lieschen Müller als Normalnutzer hat da keine Chance, wenn der liebe Admin es nicht will. Für x64 (ab Vista) gibt es dann noch den Zwang zu signiertem Code. Und MS hat verfügt, daß diese Zertifikate nicht an Normalbürger rausgegeben werden.
Flamefire hat folgendes geschrieben : |
| Wie lassen sich Kernel Hooks erkennen und vl beseitigen? |
Kommt auf die Methode an. Beseitigen geht nicht (nicht == nicht ohne mit sehr hoher Wahrscheinlichkeit das System zum Absturz zu bringen).
Flamefire hat folgendes geschrieben : |
| Kann mir jemand etwas zu lesen oder ein Tutorial zu Kernel Hooks empfehlen, wie das mit dem kernel genau funktioniert? |
"... damit ich mir endlich mein obercooles eigenes Rootkit basteln kann!" ???
Flamefire hat folgendes geschrieben : |
| Wenn ich jz also verhindern wöllte, dass jemand was mit meinem Prozess macht, hooke ich NTOpenProcess und gucke ob die PID mein ist. Wenn ja-->return -1 |
Ähem ... ein "falscher Schritt" und du hast nen schönen blauen Bildschirmschoner. Die entsprechenden Funktionen zum Testen ob es sich um gültigen Speicher handelt, funktionieren auch nicht immer und auf jedem IRQL. Aber für Malware reichts allemal. Stabilität ist da keine Anforderung. Weiß ich aus Erfahrung.
Flamefire hat folgendes geschrieben : |
| oder ist NTOpenProcess noch im UserMode eine OS-Fkt, die dann nen INT auslöst, wo dann die eigendlich Behandlung gemacht wird? |
Die Methode über Interrupts wurde mit Windows XP abgelöst. Intel (und AMD) haben dazu entsprechende Opcodes (siehe SYSENTER) bereitgestellt.
uall@ogc hat folgendes geschrieben : |
Der Ablauf ist wie folgt (wenn ich mich jetzt nicht ganz irre, ist schon 2 Jahre her wo ich damit mal was gemacht habe):
kernel32.OpenProcess -> ntdll.NtOpenProcess -> sysenter/syscall/int (je nach Prozessor und Betriebssystem) [wechsel user -> kernelmode] -> Lookup in der SSDT -> win32k.NtOpenProcess -> IRET |
Fast. NTDLL "kennt" den Index in die SSDT, daher kein "Lookup". Ist auch eine der Methoden um die Indizes zu ermitteln ;)
uall@ogc hat folgendes geschrieben : |
| NtOpenProcess/writeProceessMemory etc. wird eigentlich von jedem AntiVirus Programm gehookt um das Beenden des AV zu unterbinden und z.B. bei einem NtCreateFile aufruf wird die Datei gescannt. |
Nicht von unserm. Und das absichtlich. Denn nicht nur den Virus hindert's, sondern auch den Admin. Ach ja ... und eigentlich ist es ohnehin Humbug, da die goldene Regel unter uns AVlern lautet: wenn ein System infiziert ist, ist's eh zu spät. Aber man versucht halt (im Rahmen des Möglichen) noch was zu machen.
Flamefire hat folgendes geschrieben : |
| was ist der unterschied zwischen den beiden ntOpenProcess? |
Das eine ist ein Stub und das andere die Implementierung. ZwOpenProcess und NtOpenProcess sind in der NTDLL die gleiche Funktion. in NTOSKRNL aber nicht. Dort überprüft die eine Funktion ob der Aufrufer aus dem Usermode kommt.
Flamefire hat folgendes geschrieben : |
| dann sagt er mir, dass angeblich alle einträge in der SSDT(1) gehookt sind (kann ich kaum glauben) |
Glaub's ruhig. In KAV habe ich aufgrund eines Themas in der Delphipraxis einen Bug gefunden und gemeldet. Dabei ging es um einen schlecht implementierten SSDT-Hook. Wenn du mehr wissen willst, solltest du bspw. auf Skywing's Blog nachlesen.
Timosch hat folgendes geschrieben : |
| Kann ich nur zustimmen. Hab ich auch; ist ein sehr gutes Buch, wenn man sich mal tiefer mit der Materie befassen will. Der Titel ist recht einseitig und somit etwas irreführend. Das ist vermutlich auch das Buch, von dem uall@ogc gesprochen hat. |
Eigentlich ist das Buch nicht sonderlich tiefgreifend. Als es rauskam wußten alljene die sich damit beschäftigt hatten schon die Methoden zu nutzen bzw. zu bekämpfen. Allein, nach der Veröffentlichung gab es einen sprunghaften Anstieg von Malware die sich mithilfe der dort beschriebenen Methoden versteckt. Juhu ... freies Wissen gibt's eben auch für kriminelle Idioten.
uall@ogc hat folgendes geschrieben : |
Ja das meinte ich, außerdem sollte das Buch
Windows 2000 Internals noch ganz gut sein. Ist von Mark Russinovich (derjenige der bei MS die Sysinternals Programme programmiert). |
Ich hab's mir irgendwann bei Terrashop gekauft gehabt und es ist total oberflächlich. Klar, wenn man noch keinen Überblick über das System hat, dann hat man damit einen Volltreffer. Aber für alle die schon etwas tiefer in der Materie stecken ist es nicht zu gebrauchen. Üblicherweise werden die dort besprochenen Themen - grob gesagt - im ersten Kapitel der tiefergehenden Bücher "wiederholt" ;)
Empfehlen würde ich definitiv: "Windows NT/2000 Native API Reference" von Nebbett (stammt noch aus der Zeit als die Doku von MS karg war) und "Undocumented Windows 2000 Secrets" von Sven B. Schreiber, welches dieser in PDF-Form auf seiner Webseite anbietet. Die Bücher von OSR sind auch zu empfehlen.
Flamefire hat folgendes geschrieben : |
| Soviel ich weiß gobts noch ein 2. Buch von Greg Houghland (oder wie der heißt von Rootkits) heißt irgendwie GameHacking. Soll auch gut sein. |
"Exploiting Software" und "Exploiting Online Games".
Flamefire hat folgendes geschrieben : |
| mit welchem debugger kommt man in den Kernel (sysenter) rein? |
Mit dem in Windows eingebauten. WinDbg ist dein Freund. SoftIce ist schon lange nicht mehr unterstützt und für meinen Geschmack sind alle Alternativen (es sei denn Du hast IDA schon gekauft) einfach schlecht.
Flamefire hat folgendes geschrieben : |
| Würde mich ja mal intressieren, wie der den hook erkennt und sogar rückgängig macht. *zu uall schiel* |
Guckst Du einfach mal in den System Virginity Verifier von Joanna Rutkowska. Es gibt noch dutzende andere Tools, oft auch mit Quellen. Und rückgängig ... naja ... jetzt schiel ich gleich.
Flamefire hat folgendes geschrieben : |
| ok also das buch ist echt relativ gut. auch wenn der code dazu mehr erklärt werden könnte. |
Dazu gibt es (und gab es auch schon 2005) ausreichende Quellen im Internet.
Flamefire hat folgendes geschrieben : |
| ist es mit delphi SINNVOLL möglich treiber zu programmieren? |
Nein.
Flamefire hat folgendes geschrieben : |
| Aber das WDK ist 2GB groß...Ohne VS oder andere IDE |
Es ist etwas mehr als 600 MiB und, ja, ohne IDE. Aber auch dein normaler Compiler kommt gut ohne IDE aus. Probier's mal ... (übrigens: sogar Delphi's Compiler kommt ohne IDE aus ;))
Flamefire hat folgendes geschrieben : |
| SSDT hooks dürften da aber ziemlich gefährlich sein. wenn das programm abstürzt oder unsauber beendet wird, zeigt der hook auf falschen speicher und man kriegt nen BS |
Ach, und das ist es bei einem Multi-Threading, Multi-Core, Multi-Processor nicht? :lol:
Flamefire hat folgendes geschrieben : |
| woher weiß der SSDT handler, in welchem Kontext er die virtuellen adressen auflösen muss? |
Auch hier hilft Nachlesen!
Flamefire hat folgendes geschrieben : |
| 3) Hieß es im Buch, dass der Speicher eines Prozesses zum Teil auch KernelMode speicher ist. D.h. man kann in den KernelMode speicher schreiben, und die Adresse entspricht dann aber einer UserMode Adresse. Wie ist die Umrechnung? |
Die funktioniert über MDLs ;) ... Nachlesen!
uall@ogc hat folgendes geschrieben : |
| uallRing0 schreibt die Exe in den Kernelmode, [...], dass man Code im Kernel ausführen kann. |
Klingt nach Exploit-Methoden :D ... so kennt man Brechi :wink:
Flamefire hat folgendes geschrieben : |
| aber muss man nicht schon im kernel mode sein, um die win32k.sys und die SSDT zu überschreiben? |
Ja.
Flamefire hat folgendes geschrieben : |
| nja ich denke das beste bleibt, mit VS treiber zu erstellen. |
Nein! Bist Du des Teufels? Genau dazu gibt es die Compiler in den DDKs und WDKs. Und die unterscheiden sich in einigen Kleinigkeiten von denen in VS. Während Du also mit dem Compiler aus'm WDK gut auch UM-Code kompilieren kannst, solltest andersrum auf alle Fälle vermeiden.
Flamefire hat folgendes geschrieben : |
BTW: es gibt ja auch den borland c++ builder
eignet sich der auch? |
Aaaaaargh!!!
DDKWizard basiert aber auf den Diensten von DDKBUILD.CMD, welches wiederum das angeforderte DDK/WDK benutzt. Ob man nun aber VS oder was anderes als IDE nimmt, ist egal. Ich nehme mal an daher die Anführungszeichen?
uall@ogc hat folgendes geschrieben : |
| Den Trick den ich benutze ist, dass man auf den kompletten Arbeitspeicher auch per CreateFileA / MemoryMapping zugreifen kann (\\PhysicalMemory). Dort kann man dann alles abändern (u.a. auch die win32k.sys). DIe muss man nur im Speicher finden. |
... und Zugriff haben ;)
uall@ogc hat folgendes geschrieben : |
| [...] in den Kernelspeicher zu schreiben (mit virtuellen Adressen > 0x80000000, eben Kernelmem). Ich weiß jetzt allerdings nicht ob diese dann direkt aufgelöst werden (sodass der Code dann im jeden Prozess funktioniert). |
Ja, sollte.
Flamefire - Mi 02.12.09 11:44
danke nochmal für die (lange) antwort.
hab schon meine ersten bsp treiber geschrieben, kann damit kommunizieren und z.b. die SSDT hooken und fremde hooks entfernen (ok entfernen geht zugegebenermaßen auch mit uallring0 aus dem usermode ;-) )
aber hab halt alles mal als treiber gemacht.
mir gehts tatsächlich nicht um ein eigenes rootkit, sondern zum eigenen schutz bzw fremden schutz zun entfernen (über gamehacking lernt es sich halt am besten, da man da motivation hat und gleich was sieht ;-) )
und treiber erstelle ich mit "Visual Studio"...bzw: schreiben in VS und compilieren mit WDK
Assarbad - Mi 02.12.09 14:57
Flamefire hat folgendes geschrieben : |
| hab schon meine ersten bsp treiber geschrieben, kann damit kommunizieren und z.b. die SSDT hooken und fremde hooks entfernen (ok entfernen geht zugegebenermaßen auch mit uallring0 aus dem usermode ;-) ) |
Auch uallring0 muß den Code erstmal in den KM schaufeln und ihn dort ausführen. Nur an eine im KM verfügbare Adresse zu springen bringt reineweg garnix. Daher macht (sehr wahrscheinlich) auch uallring0 die relevanten Dinge im KM. Da solche Hacks im allgemeinen nur funktionieren bis die jeweilige "Lücke" behoben ist, beschäftige ich mich mit ihnen nur wenn ich muß :lol:
ABER: zum Thema Hooks entfernen. Soll ich mich wiederholen oder liegt Dir die Stabilität deines Systems (oder dessen auf dem Dein Code läuft) nicht am Herzen?
Hier mal nur ein paar wenige Fehlerquellen. Wir nehmen an, daß Du einen SSDT-Hook implementiert hast. Der Zeiger am entsprechenden Index zeigt aber, da Du ja vorsichtig bist/warst, nicht direkt auf deine Funktion sondern bspw. auf ein Jumppad (einfach allozierter Speicher den Du nie wieder freigibst oder eine Lücke in einem Kernelmodul, bspw. NTOSKRNL).
Beim Hooken oder davor könntest Du folgende Probleme haben:
- Kein Spinlock, daher funkt ein anderer Kern oder Prozessor dazwischen
- Jemand anderes war vor Dir da
- Jemand anderes ist nach Dir da
- Jemand war vor und nach Dir da
- Der andere Code schert sich nicht um Stabilität oder hat nichtmal annähernd die Erfahrung sowas zu machen
- Jemand anderes hält kein Spinlock und hookt zur gleichen Zeit. Da Du ein Spinlock benutzt steht sein Code zufällig nach dem Auslesen des Zeigers aber vor dem Austauschen. Sobald Du das Spinlock aufgibst, ist die Hölle los ...
Nach dem Hooken, bzw. beim Entfernen:
- Kein Spinlock, daher funkt ein anderer Kern oder Prozessor dazwischen
- Kein Entfernen mehr nötig, da es jemand anderes gemacht hat, aber irgendein (oder mehrere) Thread(s) im System ist derzeit an einer unglücklichen Codestelle und wird das System zum Absturz bringen wenn er die Ausführung wieder aufnimmt
- Jemand war vor Dir da. Der hat auch mal fröhlich gehookt, kein Jumppad benutzt und du hast dir als "Orginaladresse" eine gemerkt, die in seinem Treiberimage im Speicher liegt. Der war aber so frei den Hook zu "entfernen" und da er ja nicht wissen konnte, daß Du auch einen Hook gesetzt ha(tte)st, hat er dich leider nicht über die echte Orginaladresse informiert. Ergo: Dein Code springt an eine Position an der zuvor der fremde Treiber geladen war und nun nicht mehr ist
- Entfernen geht nur einer nach dem anderen. Da Du ordentlicherweise ein Spinlock hältst, ist das kein Problem. Du entfernst alse einen Hook nach dem anderen. Beim vorvorletzten geht was schief. Jemand war nach Dir da, der Zeiger entspricht nicht mehr dem Wert den Du hinterlassen hast. Was machst Du? Übrigens der vorletzte Zeiger wurde auch manipuliert und zufälligerweise basiert der fremde Code auf der Annahme daß die entsprechenden beiden Funktionen gehookt sind.
Und hier noch
der Direktlink [
http://www.nynaeve.net/?p=210] auf Skywing's Blog auf den ich Dich schon zuvor verwies. Und jetzt kommst Du!
Flamefire hat folgendes geschrieben : |
| mir gehts tatsächlich nicht um ein eigenes rootkit, sondern zum eigenen schutz bzw fremden schutz zun entfernen (über gamehacking lernt es sich halt am besten, da man da motivation hat und gleich was sieht ;-) ) |
Überprüfen kann ich es nicht und letztendlich ist es mir vermutlich auch egal. Ich habe nur eben wöchentlich mit Rootkits zu tun und die meisten davon sind einfach nur schlecht programmiert. Es gibt allerdings auch durchaus elegante ...
cisum - Mi 02.12.09 15:57
Leider konnte ich bisher keinen Shop finden, in dem dieses Buch noch verfügbar ist.
kennt ihr vielleicht einen, in dem es das Buch noch gibt oder will vielleicht jemand dieses Buch loswerden?
Vielen Dank im Vorraus!
Flamefire - Mi 02.12.09 16:44
sry aber ich bin echt neu in dem gebiet...darum bisher kein spinlock verwendet
spinlock ist doch dafür da, dass man mehrere threads synchronisiert.
durch interlockedexchange macht das doch aber das betriebssystem, oder irre ich mich da?
so viel zum hooken, jetzt zum unhooken von der SSDT, die unbekannt gehookt ist:
die originalfunktionsadresse (also der pointer, der in der SSDT stehen müsste) ist bekannt (auslesen aus der kernel-exe)
-->kein problem, den pointer auf ungültigen mist zu setzen
-spinlock unnötig, basierend auf obiger annahme
-wenn jmd andres vorher entfernt hat, änder ich nix mehr
-originaladresse bekannt->kein prob
-gegen solche annahmen, wie dass eine gehookte funktion auf einer andren gehookt basiert, kann ich nix machen.
einzige variante um das halbwegs auszumerzen wäre, alle prozessoren zu locken (IRQL erhöhen) und dann erst zu enthooken
bringt immer noch probleme, wenn ein aufruf gerade mittendrin ist...in meinen problemen bisher aber kein thema. ich kann annehmen, dass das nicht der fall ist.
"Rootkit" ist i.A. ja schon ein treiber, der bestimmten zugriff verhindert. ich versuche derzeit das "rootkit" XTrap auszuschalten...
was (leider) auch viel zu einfach möglich war, ist den antivir service zu beenden (aus usermode ohne treiber, aber mit adminrechten unter xpSP3), was ich als test mal gemacht hatte. antivir hat mein programm nicht bemängelt o.ä. nichtmal als verdächtig
und zu uallring0: es ging um das entfernen. und da reicht es schreibzugriff auf kernelspeicher zu erhalten. und das geht mit adminrechten über mapping recht elegant. im internet kursieren noch einige anleitungen zu ähnlichen vorgehensweisen über \\physicalmemory (oder so)
PS: das buch hab ich z.b. aus der slub geliehen ;-)
Assarbad - Mi 02.12.09 18:37
Flamefire hat folgendes geschrieben : |
sry aber ich bin echt neu in dem gebiet...darum bisher kein spinlock verwendet
spinlock ist doch dafür da, dass man mehrere threads synchronisiert. |
Spinlocks sind dazu da, dass kein anderer Prozessor (oder Kern) zu diesem Zeitpunkt was machen kann.
Flamefire hat folgendes geschrieben : |
| durch interlockedexchange macht das doch aber das betriebssystem, oder irre ich mich da? |
Implementiert wird das auf CPU-Ebene indem der Adressbus fuer die Dauer eines Opcodes gesperrt wird, wenn ich mich recht entsinne.
Flamefire hat folgendes geschrieben : |
| die originalfunktionsadresse (also der pointer, der in der SSDT stehen müsste) ist bekannt (auslesen aus der kernel-exe) |
Aus
welcher "kernel-exe" [
http://en.wikipedia.org/wiki/Ntoskrnl#Names_of_kernel]?
Zum Rest auessere ich mich nicht mehr. Es scheint sinnlos zu sein. Viel "Erfolg".
Flamefire - Mi 02.12.09 19:49
öhm. sry. wollte dich nicht vergraulen. ich hab nur einen teil gelesen und leite daraus (für mich) logische schlüsse ab.
wenn ich mich in irgendeinem punkt vertan habe, dann würde ich mich schon über berichtigungen freuen.
denn z.b. wozu brauche ich ein spinlock, wenn der komplette adressbus gesperrt ist? besser kann man doch kaum schützen, oder?
spinlocks basieren eh auf den interlocked-funktionen (oder auf vergleichbaren, da sonst die sperrvariable zum problem wird)
mit "kernel-exe" meinte ich die derzeit geladenen. das ermittle ich per QuerySystemInformation. wollte damit eben genau das andeuten, dass ich auch die richtige nehme.
das einzige problem bei enthooken sehe ich nur, dass ein laufender aufruf von einem anderen abhängt, der gerade entfernt wurde
wie gesagt: nimm bitte meine äußerungen nicht als "was du sagst intressiert mich nicht" o.ä. sondern ich versuche nur, darzustellen und zu erklären, was ich bisher kenne.
Assarbad - Mi 02.12.09 20:43
Flamefire hat folgendes geschrieben : |
| denn z.b. wozu brauche ich ein spinlock, wenn der komplette adressbus gesperrt ist? besser kann man doch kaum schützen, oder? |
Ich konkretisiere:
Assarbad hat folgendes geschrieben : |
| Implementiert wird das auf CPU-Ebene indem der Adressbus fuer die Dauer eines Opcodes gesperrt wird, wenn ich mich recht entsinne. |
Sowas sieht dann
so [
http://ref.x86asm.net/geek.html#xF0] aus:
Flamefire hat folgendes geschrieben : |
| spinlocks basieren eh auf den interlocked-funktionen (oder auf vergleichbaren, da sonst die sperrvariable zum problem wird) |
Das ist hardware-spezifisch und daher im HAL. Fuer x86 basiert der Teil auf
BTS [
http://ref.x86asm.net/geek.html#x0FAB] (mit LOCK Praefix). Und wenn ich das in IDA jetzt auf die Schnelle korrekt gesehen habe, wird danach der
PAUSE-Opcode [
http://cache-http://www.intel.com/cd/00/00/01/76/17689_w_spinlock.pdf] benutzt um den Prozessor schlafenzulegen.
| Zitat: |
Description
Improves the performance of spin-wait loops. When executing a “spin-wait loop,” a Pentium 4 or Intel Xeon processor suffers a severe performance penalty when exiting the loop because it detects a possible memory order violation. The PAUSE instruction provides a hint to the processor that the code sequence is a spin-wait loop. The processor uses this hint to avoid the memory order violation in most situations, which greatly improves processor performance. For this reason, it is recommended that a PAUSE instruction be placed in all spin-wait loops.
An additional function of the PAUSE instruction is to reduce the power consumed by a Pentium 4 processor while executing a spin loop. The Pentium 4 processor can execute a spin-wait loop extremely quickly, causing the processor to consume a lot of power while it waits for the resource it is spinning on to become available. Inserting a pause instruction in a spin-wait loop greatly reduces the processor’s power consumption.
This instruction was introduced in the Pentium 4 processors, but is backward compatible
with all IA-32 processors. In earlier IA-32 processors, the PAUSE instruction operates like a NOP instruction. The Pentium 4 and Intel Xeon processors implement the PAUSE instruction as a pre-defined delay. The delay is finite and can be zero for some processors. This instruction does not change the architectural state of the processor (that is, it performs essentially a delaying no-op operation).
This instruction’s operation is the same in non-64-bit modes and 64-bit mode.
([url=http://www.intel.com/Assets/pdf/manual/253667.pdf]Quelle[/url]) |
Flamefire hat folgendes geschrieben : |
| mit "kernel-exe" meinte ich die derzeit geladenen. das ermittle ich per QuerySystemInformation. wollte damit eben genau das andeuten, dass ich auch die richtige nehme. |
Dann ist der Teil i.O.
Flamefire hat folgendes geschrieben : |
| das einzige problem bei enthooken sehe ich nur, dass ein laufender aufruf von einem anderen abhängt, der gerade entfernt wurde |
Und wie willst Du das unter Kontrolle bekommen? Und vor allem sollte
der Beitrag von Skywing [
http://www.nynaeve.net/?p=210] hier vielleicht mal bei Dir gesunde
Zweifel an dem was Du versuchst aufkommen lassen (irgendwie zweifelst Du scheinbar zuerst an Fakten oder Aussagen anderer und dann an Deinen Ideen). Dazu vielleicht nochmal direkt
der Link [
http://www.osronline.com/showThread.cfm?link=56683#T2] zur NTDEV-Liste wo ich 2004 (also bevor ich beruflich mit Treibern zu tun hatte) von Don Burn zusammengeschissen wurde. Das Thema hat Skywing von seinem Beitrag aus verlinkt. Also: einfach mal zuerst das NTDEV-Thema von 2004 und danach den Blogbeitrag von Skywing zu Gemuete fuehren und danach reden wir weiter.
Flamefire - Do 03.12.09 00:00
was ist der nutzen eines spinlocks gegenüber der interlocked operation beim enthooken unabhängiger funktionen (also ohne den sonderfall, das eine gehookte funktion, von einer anderen abhängig ist)
den sonderfall unter Kontrolle zu bekommen, ist, (denke ich) nicht möglich. AFAIK ist es nicht möglich, festzustellen, ob ein prozess gerade in einer funktion ist, und wenn ja, diesen daraus zu "entlassen" und dann erst weiterzumachen (ok...alle PEB->unterstrukturen auf EIP prüfen und ggfls warten wäre ne variante aber immer noch unsicher)
den blogbeitrag hab ich gelesen. recht intressant, auch wenn ich bei einigen teilen nicht ganz mitkomme.
z.B. den teil, warum ein SSDT hook per pointer modification zu nem deadlock führt
i.A. sind die fehler im code zu ca 50% synchronisierungsprobleme...die hat man fast immer ;-)
der rest ist...unvorsichtiges zeug. also zb das mit dem status, und dem kernel handle
aber echt nicht schlecht. an vieles denkt man wirklich nicht so schnell
Assarbad - Do 03.12.09 01:44
Flamefire hat folgendes geschrieben : |
| was ist der nutzen eines spinlocks gegenüber der interlocked operation beim enthooken unabhängiger funktionen (also ohne den sonderfall, das eine gehookte funktion, von einer anderen abhängig ist) |
Die Tatsache, dass das Entfernen kaum mit einer einzigen Aktion (also einem Opcode) geschehen kann. Oder habe ich was verpasst?
Wie gesagt, wenn es sich um was handelt was deine Rechner nie verlaesst, ist die Stabilitaet ja auch zweitrangig. Aber beim Kunden brauchste auch mit einer Sicherheitsanwendung nicht antanzen wenn bei deren Benutzung u.U. der Server blau macht ... und wie oft oeffentlich zugaenglicher aber nur prototypenreifer Code mal eben in kommerziellen Anwendungen landet will ich garnicht wissen. ... auch nicht an wievielen der kommerziellen Anwendungen Menschenleben haengen.
Flamefire hat folgendes geschrieben : |
| i.A. sind die fehler im code zu ca 50% synchronisierungsprobleme...die hat man fast immer ;-) |
... nur dass sie im Kernelmode zu einem
Systemabsturz fuehren, im Usermode aber "nur" zu einem
Programmabsturz. Und deine bisherigen Einwuerfe klangen nicht danach dass Du auch nur die "offensichtlichen" Probleme alle erkannt haettest ;)
Flamefire - Do 03.12.09 08:30
ähm...das entfernen läuft so:
-herausfinden der adresse des eintrags in der ssdt (offset)
-herausfinden des originalptr
-schreiben das originalptr an die adresse
kritischer abschnitt ist das letzte. durch interlocked funktioniert das. rest kann nicht verändert werden
damit habe ich nur einen opcode, oder?
ja ich weiß...programmfehler im treiber-->bsod
hatte ich oft genug. aber probier ja noch rum um erst mal gut reinzukommen. inzwischen krieg ich aber die teile recht gut hin ohne bsod. bisher noch ohne validation aber das kommt ja noch. und für meine anwendung wird das ding nicht sehr groß, wodurch es da (hoffentlich) kaum probleme zu suchen gibt.
Assarbad - Do 03.12.09 15:48
Flamefire hat folgendes geschrieben : |
ähm...das entfernen läuft so:
-herausfinden der adresse des eintrags in der ssdt (offset)
-herausfinden des originalptr
-schreiben das originalptr an die adresse
kritischer abschnitt ist das letzte. durch interlocked funktioniert das. rest kann nicht verändert werden
damit habe ich nur einen opcode, oder? |
Und wo bleibt das Überprüfen ob jemand schon vor Dir dran rumgefummelt hat? Nichtmal InterlockedCompareExchange bekommt das hin. Das Ergebnis des Vergleichs bekommst Du so höchstens
nach der Austauschaktion. Aber ist ja okay, war ja nur ein kleines Detail von dutzenden die man übersehen könnte ...
So, das war jetzt mein letzter Beitrag zum Thema . Wir haben es lange genug durchgekaut. Das Szenario mit dem Überprüfen vor Austausch übrigens auch, aber das hattest Du innerhalb weniger Beiträge wieder "vergessen".
Flamefire hat folgendes geschrieben : |
| bisher noch ohne validation aber das kommt ja noch. und für meine anwendung wird das ding nicht sehr groß, wodurch es da (hoffentlich) kaum probleme zu suchen gibt. |
Eins noch. Wenn Du Validierung über's WHQL meinst, informier Dich lieber vorher nochmals, sonst könnte Dein Geschäftsmodell infrage stehen. Treiber für VIsta und neue müssen übrigens immer als x86 und x64 bereitstehen, was mit KM-Hooks und Patchguard ab Vista x64 nicht mehr so einfach ist.
Flamefire - Do 03.12.09 17:54
als validierung meinte ich hier eine mehr oder weniger vollständige analyse des codes auf fehler wie den besprochenen, bzw im blog genannten.
ich verstehe immer noch nicht, was ich denn bei der SSDT überprüfen sollte?
ich lese. vergleiche den gelesenen wert mit dem original. alles in meinem speicher, den ich einfach mal als konsistent und nicht von außen veränderlich ansehe. (man kann ja davon ausgehen, dass niemand grade in seinem laufenden programm variablen ändert, und wenn doch, ist das nicht mein problem)
wenn vergleich negativ-->ssdt eintrag gehookt-->enthooken
ob den da schon jmd vorher enthookt hat, ist mir doch egal. dann überschreibe ich halt den originaleintrag mit dem originaleintrag...passiert doch nix, oder?
darum habe ich das nicht vergessen, sondern mit obiger argumentation als nicht sinnvoll angesehn.
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2026 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!