Winapi Hooks mittels asm



  • Okay... Ich fang mal an mein Vorhaben zu erklären:

    Da mein Vater irgendeine komische Malware eingefangen hat (also auf seinem Rechner) hab ich beschlossen gleich eine Art Software für Hooks zu machen, wo man dann relativ einfach Hooks auf wichtige Funktionen legen kann... dies könnte auch ausgebaut werden zu einer Art Programm - Firewall indem es nur erlaubten Programmen gestattet zu starten... wenn sich dann irgendein exploit nen eigenen Prozess starten will so soll die "Programm - Firewall" das abfangen... naja ich glaub man kriegt den Punkt raus... nun ist aber mein asm - Wissen leider recht dürftig...

    [edit:] Die Malware bei meinem Dad erstellt immer xxxx.nls Dateien und zwar jede Minute... also will ich auf User-Ebene die Funktion CreateFileA und wenns noch andere gibt die er da verwenden kann, so auch diese Hooken.. dann alle Prozesse die mich lassen durchprobieren und sehen obs wo was bringt...

    Okay: dann beschreib ich am besten mal wie weit ich bin und wo das Problem leigt:
    Mein Vorgehen war so: Ich erstelle in einem ausgewählten Prozess eine Memory page die ausgeführt werden darf... dann kopier ich die asm befehle (also schon als op codes) rein... und setzte einen call auf die addresse der Page als ersten Befehl in die Funktion CreateFileA...
    a) entweder eine Biliothek laden (von mir) und dann dorthin springen -> diese übernimmt die Anzeige für den user, fragt den ob er den Befehl erlaubt und führt anschließend den code aus...

    b) gleich dirket alles was zu tun ist in asm schreiben, alles abändern was abzuändern ist und dann wieder brav zurückspringen...

    naja für den anfang wollt ich mal testen ob das überhaupt so funktionieren kann-
    und das Problem ist die Addresse von den Funktionen... z.b. MessageBoxA -> woher bekomme ich die Addresse? Hab das bei einer Testanwendung so gelöst, dass ich eben die Addresse im Prozess hole und dann in eine mov eax, xxxxxxx die Addresse kopiere und das funktioniert auch... nur wie gehe ich da vor wenn ich den anderen Prozess eben hooke?

    wenn Process1 (P-Firewall) und Process2 (irgendeine zu hookende exe) GetProcAddress(ihre Modulehandle, MessageBoxA) aufrufen, sind dass dann die gleichen Addressen? ich komm da leider ned weiter... und das testen hat mich jetzt sicher schon ne weile gekostet... hat da vielleicht wer ne idee und/oder Erfahrung.

    Auch eine Liste von Funktionen die man zum starten von Prozessen auf USER-Ebene aufrufen kann oder File-Funktionen wären echt hilfreich... allerdings brauch ich nur die niedrigste Ebene: also wenn die Funktion fopen z.b. CreateFileA aufruft... dann muss ich ja nur CreateFileA hooken...

    Anmerkung:
    Ich weiß, dass man dieses Problem normalerweise löst indem man die tabelle patched, wo die Addressen für die importierten Funktionen stehen... aber da ich das schonmal probiert habe und leider irgendwie nicht weitergekommen bin, wills ichs mal auf diese Methode probieren...

    Ich will mich jedenfalls bei allen Bedanken, die sich die Mühe gemacht haben es bis hier her zu lesen... Ich sag bescheid wenn ich wieder was rausgefunden hab und unter Umständen könnt ihr bald meine Programm-Firewall testen 😃 obwohl das sicher noch total lange dauern wird... 😞
    mfg Manuel



  • Okay.. das Problem hat sich ein wenig reduziert... würde mir schon stark helfen wenn jemand weiß, ob die Funktionen der Kernel32 und der User32 (für msgbox) wobei die kernel wirklich wichtig ist.. (beim endgültigen programm soll sowieso ne dll geladen werden, die ich dann sowieso in c++ schreiben kann und alles verwenden kann was man halt so zur verfügung hat... egal..

    also das Problem ist folgendes: Wenn man mit GetProcAddress die Addressen der dll funktionen holt (also von kernel und user) dann bekomme ich diese Addressen:

    MessageBoxA: [0x77D3B00A]
    GetProcAddress: [0x77E5B332]
    LoadLibraryA: [0x77E5D961]

    Kann ich die als fix ansehen... also auch fix eincoden? Nach meinem verständnis schon, denn schließlich ändert sich die Kernel32 ja nicht und die Addressen bleiben gleich....?! Wenn ich die kernel32 dann verändere gilt das aber nur für den prozess in dem ich es tue, oder? Irgendwie ist das alles recht kompliziert... ich dachte immer die dll und ihre Funktionen werden nur einmal geladen... aber anscheinend ist das ein klein wenig anderes? Wenn jemand bescheid weiß so würd er mir damit sehr helfen... und ne menge zeit ersparren... sonst müsst ich das nämlich nochmal testen... und das kann dauern... besonders bei meinen dürftigen asm kenntnissen
    Wie auch immer mfg Manuel



  • Ich habe zwar keine besondere Ahnung von Windows, aber die Adressen dieser Funktionen sind so weit ich weiss nicht fix. Wenn du das fix eincodest, mag das vielleicht auf deinem System gerade mal laufen, aber die Wahrscheinlichkeit ist hoch, dass es das auf anderen nicht tut.



  • Hm, naja fix eincoden... naja ich meinte mehr so: Also mein Programm schreibt zur Laufzeit die Addresse (ermittelt wia GetProcAddress) rein... also in den "shell-code" oder wie man das nennt... das wär kein Problem... ist eben nur wichtig ob das jetzt für alle Prozesse gleich ist... hm.. nach meinen Nachforschungen ist es das, aber naja... es gibt in Moment sowieso andere Fragen die mich quälen:

    Ich dachte immer die Kernel32.dll wird nur einmal geladen... das würde bedeuten die Veränderung müsste dann alle Prozesse betreffen... andererseits muss sie aber im Addressraum des Prozesses sein, der gerade läuft... hm.. also wenn ich jetzt in die memory page was anderes reinschreib, müsste es entweder: a) für alle Prozesse drinnstehen, weils halt wirklich geändert wurde... b) beim nächsten Thread-switch oder wenn halt die kernel neu geladen wird, also der teil auch wieder neu geladen werden, -> also Änderung hat keine Auswirkungen.. Nach meinem Verständniss dürfte es aber nicht die Auswirkungen haben, die ich eigentlich anstrebe... hm...
    Glaub aber dass passt eigentlich garned hier her.. sollte vielleicht ins WINAPI Forun verschoben werden.. dachte nur dass ich hier die Hardcore lowlevel Männer finde, die sich da vielleicht zufällig auf Windows auskennen wie das alles genau abläuft... naja vermutlich werd ichs wohl eh lassen, denn irgendwie glaub ich, dass ich damit kaum was aufspühren könnte... hm mal sehen... vielleicht komm ich mal wieder lust... Danke jedenfalls für eure Zeit..
    mfg Manuel



  • Manuelh87 schrieb:

    Ich dachte immer die Kernel32.dll wird nur einmal geladen...

    Das hängt vom "Windows" ab. Vom Betriebssystem "Windows" gibt es (einfach gesagt) zwei Versionen :

    (1) -> Windows 95, 98, ME
    (2) -> Windows NT, 2000, XP

    Beide Versionen unterscheiden sich im Speichermanagement wie Tag und Nacht.

    Unter (1) gibt es Speicherbereiche auf die alle Prozesse zugreifen können.

    KERNEL32.DLL liegt in diesem Bereich. Deshalb haben Änderungen an dem von KERNEL32.DLL belegten Speicherbereich immer Auswirkungen auf alle Prozesse.

    Unter (2) gibt es solche Speicherbereiche nicht mehr.

    Jeder Prozess lädt sich seine "eigene" KERNEL32.DLL in seinen Adressraum. Änderungen würden dann nur einen einzigen Prozess betreffen.

    Manuelh87 schrieb:

    .. sollte vielleicht ins WINAPI Forun verschoben werden

    Aller Erfahrung nach bestehen "Programm - Firewalls" auch aus 90% WinAPI und 10% Assembler.



  • Also ich würde in diesem Fall wie ein Virusprogrammierer vorgehen.

    1. Aktuelle Position im Speicher finden. (delta offset)
    2. kernel32.dll ImageBase Adresse finden. (gucke dir die Tuts über win32 shellcode programmierung an).
    3. Und dann finde ich die Funktionsadressen (by scanning Export Directory Table).

    Das funktioniert 100% egal welches OS, ob 95 oder XP/NT.

    ;find kernel32.dll image base address.  (thanks to skape)
    	xor		eax, eax 							
    	ASSUME 	FS:NOTHING
    	mov 	eax,fs:[eax+30h]				
    	test	eax,eax							
    	js 		__kernel_9X 						
    __kernel_NT:
    	mov 	eax,[eax+0Ch] 					
    	mov 	esi,[eax+1Ch] 					
    	lodsd 									
    	mov 	eax,[eax+8h] 					
    	jmp 	__kernel_finish				
    __kernel_9X:
    	mov		byte ptr[ebx+winNT], 0	;we are at a win9X machine
    	mov 	eax, [eax+34h]
    	lea 	eax, [eax+7Ch]
    	mov 	eax, [eax+3Ch]				
    __kernel_finish:
    	; EAX == kernel32.dll image base address
    

    und hier die Funktion die APIs findet:

    GetFuncAddr PROC
    
    	;search for function address by scannig Export Directory Table. (thanks to skape)
    	pushad
    	mov 	ebp, [esp+28h]
    	mov 	eax, [ebp+3Ch]
    	mov 	edx, [ebp+eax+78h]
    	add 	edx, ebp
    	mov 	ecx, [edx+18h]
    	mov 	ebx, [edx+20h]
    	add 	ebx, ebp
    GFA_loop:
    	jecxz 	GFA_notfound
    	dec 	ecx
    	mov 	esi, [ebx+ecx*4]
    	add 	esi, ebp
    GFA_compute_hash:
    	xor 	edi, edi
    	xor 	eax, eax
    	cld
    GFA_compute_hash_again:
    	lodsb
    	test	al, al
    	jz 		GFA_compute_hash_finished
    	ror 	edi, 0Dh
    	add 	edi, eax
    	jmp 	GFA_compute_hash_again
    GFA_compute_hash_finished:
    GFA_compare:
    	cmp 	edi, [esp+24h]
    	jnz 	GFA_loop
    	mov 	ebx, [edx+24h]
    	add 	ebx, ebp
    	mov 	cx, [ebx+2*ecx]
    	mov 	ebx, [edx+1Ch]
    	add 	ebx, ebp
    	mov 	eax, [ebx+4*ecx]
    	add 	eax, ebp
    	mov 	[esp+1Ch], eax
    GFA_finish:
    	popad
    	ret 	8
    GFA_notfound:
    	xor		eax,eax
    	mov		[esp+1Ch], eax
    	jmp		GFA_finish
    
    GetFuncAddr ENDP
    

    oder was genau willst du?



  • [quote="merker"]

    Manuelh87 schrieb:

    Jeder Prozess lädt sich seine "eigene" KERNEL32.DLL in seinen Adressraum. Änderungen würden dann nur einen einzigen Prozess betreffen.

    um genau zu sein es wird nu Datensegment und sonstiges von kernel32.dll in Adressraum jedes Processes geladen.

    Der Codesegment wird nur einmal im Speicher geladen und steht allen Processen zu verfügung.

    bei win XP z.B. at address: 0x7C800000



  • Manuelh87 schrieb:

    Kann ich die als fix ansehen... also auch fix eincoden? Nach meinem verständnis schon, denn schließlich ändert sich die Kernel32 ja nicht und die Addressen bleiben gleich....?! Wenn ich die kernel32 dann verändere gilt das aber nur für den prozess in dem ich es tue, oder? Irgendwie ist das alles recht kompliziert... ich dachte immer die dll und ihre Funktionen werden nur einmal geladen... aber anscheinend ist das ein klein wenig anderes? Wenn jemand bescheid weiß so würd er mir damit sehr helfen... und ne menge zeit ersparren... sonst müsst ich das nämlich nochmal testen... und das kann dauern... besonders bei meinen dürftigen asm kenntnissen
    Wie auch immer mfg Manuel

    Also die Adresse darf auf keinen Fall hardcoded sein.

    Es kann sein dass mit nächstem ServicePack ImageBase Adress von kernel32.dll anderes wird.

    Die adressen sind auch SP für SP unterschidlich.


Anmelden zum Antworten