Passage a Win2000 (NT5) et creation de Kernel-Mode Driver Petit Edito :) Vous vous etes deja demandé pourquoi vous crackiez?? Non vraiment, vous ne vous etes jamais demande pourquoi vous avez cracké ce foutu programme dont vous n'avez rien à faire en fait? Pourtant vous etes reste longtemps dessus à rechercher peut-etre l'unique byte que vous modifierez plus tard pour 'ameliorer' ce prog, c'est assez bizzare n'est-ce pas! En fait ce n'est pas par besoin que l'on reverse personne n'a besoin d'utiliser tout les nouveaux programmes qui sortent surtout lorsque ces sharewares sont denué d'interet car ecrit à la va-vite par des auteurs voulant seulement gagner de l'argent sur le dos de pauvre utilisateur innocents.En effet la plupart des possesseurs de PC ne se doutent meme pas qu'il est possible de trouver un serial sans passer par le bruteforce! Ou de modifier qqs byte d'un programme pour le rendre moins ennuyeux :) Donc nos motivations sont autres, certains crackent peut-etre pour la gloire pour etre reconnu des autres mais une bonnes majorite a mon avis le fait par plaisir, plaisir d'etablir une sorte de compétition entre le programmateur et nous, plaisir de faire travailler sa matière grise pour comprendre ce que fait cette routine, pour decouvir pourquoi le prog ne se lance pas lorsque softice est loadé... On arrive ainsi a devenir independant d'énormes boites d'informatiques qui en rendant leur logiciels de plus en plus facile d'acces amènent l'utilisateur normal a devenir dependant completement de l'OS...Imaginez un peu que Microsoft change toutes ses API et ne donne les explications qu'en echange de forte somme d'argent...(c'est deja un peu le cas car de nombreuses API sont non documentees...) Il n'y aurait plus que des logiciels fabriques par de grosses boites et on n'y pourrait rien...C'est pour cela qu'il est presque necessaire que certains essayent tjrs de pousser plus loin leur connaissance de l'OS etc qu'ils utilisent :) A mon avis win2000 va rapidement s'installer a la place des win9x car il est plus stable, plus securise...Et c'est pour ca que je pense qu'il faut passer a win2000 le plus rapidement possible car au debut il y a quand meme beaucoup de changement...Win9x n'etait que du DOS graphique vous savez comme il est facile de passer en ring0 a partir de code en ring3, sous NT (2K) cela est bcp plus complique il faut avoir recours aux KMD :) Bon maintenant on arrive à la partie interressante de ce chtit texte :) Création de KMD (Kernel-Mode Driver): Les KMD representent en gros a NT ce que les vxd sont a 9x...Sous NT il y a plusieur types de drivers mais ceux qui sont execute en ring0 sont les KMD c'est pourquoi ils nous interressent :) Car on peut avoir le "pouvoir absolu" grace a eux sous NT... **********Enregistrer et loader dynamiquement un KMD************* Je ferais un prochain tut la-dessus car pour l'instant g juste modifier certaines sources provenant du NTddk pour loader mon KMD *******************Init Routine********************************** Lors de l'appel a la routine StartService la fonction contenue par le KMD ayant pour but de faire les initialisations est executees... Cette routine doit donc faire certaines taches necessaires!Elle se doit en effet de creer un nom de driver du KMD pour qu'on puisse obtenir par la suite un handle de ce dernier via la fonction CreateFileA.Elle doit egalement donner au system des informations sur l'addresse des fonctions de dispatchs qui seront appellees lors d'evenement relatifs au KMD (utilisation de DeviceIoControl...) Bon maintenant que l'on connait les fonctions primordiales qui doivent etre realisee par une routine d'initialisation voyons un peu de code :) NB:Une bonne partie de ce code provient de Numega (NTIce) de certaines textes d'ElICZ,et de MS [merci au 2 premiers :) ...] DeviceName db '\',0,'D',0,'e',0,'v',0,'i',0,'c',0,'e',0,'\',0,'N',0,'T',0,'A',0,'L',0,'L',0,0,0 DosDeviceName db '\',0,'D',0,'o',0,'s',0,'D',0,'e',0,'v',0,'i',0,'c',0,'e',0,'s',0,'\',0,'N',0,'T',0,'A',0,'L',0,'L',0,0,0 DriverEntry PROC USES EBX ESI EDI, DriverObject, RegPath LOCAL DeviceObject :DWORD LEA EDI, DevNameUnicode2 INVOKE RtlInitUnicodeString , EDI, ADDR DeviceName ;returns EAX=0 if [EDI] != 0 on prepare notre string DeviceName LEA ECX, DeviceObject MOV ESI, DriverObject ASSUME ESI: PTR DRIVER_OBJECT ExtensionSize EQU EAX ;0 DevType EQU (00000022h SHR 16) DevCharacteristic EQU EAX ;0 Exclusive EQU EAX ;FALSE INVOKE IoCreateDevice , ESI, ExtensionSize, EDI, DevType, DevCharacteristic , Exclusive , ECX ;on cree un ?????????? TEST EAX, EAX JL CreateDeviceFailed MOV EDX, DeviceObject OR (PDEVICE_OBJECT [EDX]).FLAGS, DO_BUFFERED_IO MOV EAX, OFFSET StandardDispatch ;on rempli la structure qui nous est passee pour donner les offsets ;des fonctions de dispatch MOV dword ptr [ESI+34h], OFFSET Unload ;Lorsqu'on fermera le KMD MOV dword ptr [ESI+38h], EAX ;StandardDispatch pour les events IRP_MJ_CREATE et IRP_MJ_CLOSE MOV dword ptr [ESI+40h], EAX MOV dword ptr [ESI+70h], OFFSET Dispatch ;Pour les autres evenements (code passe par DeviceIoControl.....) MOV EAX, OFFSET SymLinkNameUnicode ;db 500 dup (?) PUSH EDI PUSH EAX INVOKE RtlInitUnicodeString, EAX, ADDR DosDeviceName ;On initialise comme plus haut 7 string CALL IoCreateSymbolicLink ;on cree le nom qui sera utilise lors de createfile TEST EAX, EAX JGE SymLinkCreated PUSH EAX INVOKE IoDeleteDevice , DeviceObject ;y a eu un probleme on close de Device POP EAX SymLinkCreated: CreateDeviceFailed: RET DriverEntry ENDP Bon maintenant y reste plus qu'a traiter les 3 autres routines importantes **********Standard Dispatch (IRP_MJ_CREATE et IRP_MJ_CLOSE)************* StandardDispatch PROC DeviceObject, pIRP MOV ECX, pIRP SUB EDX, EDX PUSH EDX ;STATUS_SUCCESSFUL MOV dword ptr [ECX+1Ch], EDX ;1C .IoStatus.Information MOV dword ptr [ECX+18h], EDX ;18 .IoStatus.Status INVOKE IoCompleteRequest, ECX, EDX POP EAX RET StandardDispatch ENDP En fait cette routine ne fait presque rien :) sauf mettre eax a 0 -> STATUS_SUCCESSFUL et invoker IoCompleteRequest pour que tout se passe en douceur y faut mieux l'invoker lors de chaque fin de routine de dispatch **********************************Unload******************************** Unload PROC DriverObject INVOKE IoDeleteSymbolicLink, ADDR SymLinkNameUnicode ;on supprime le nom qu'on avait donne a notre device MOV EAX, DriverObject INVOKE IoDeleteDevice , (PDRIVER_OBJECT [EAX])._PDEVICE_OBJECT ;on remove notre device RET Unload ENDP *************Dispatch (Tous les autres evenements)*************** Dispatch PROC USES EBX ESI EDI DeviceObject, pIRP MOV ECX, pIRP ASSUME ECX: PTR _IRP MOV EDI, [ECX].PCurrentIrpStackLocation MOV ESI, [ECX].SystemBuffer MOV EAX, [EDI+0Ch] ;Control Code passe par IoDeviceControl PUSH ECX ;save IRP CMP EAX, MaxService ;Notre code est valide? JNA @f@ ItsBad: MOV EAX, 0C00000E8h ;STATUS_NOT_IMPLEMENTED SUB EDX, EDX JMP QuitDispatch @f@: call CeQueVousVoulezEnFontionDeEAX QuitDispatch: POP ECX ;get IRP PUSH EAX MOV [ECX].IoStatus.Information, EDX ;sets BytesReturned of DeviceIoControl MOV [ECX].IoStatus.Status, EAX SUB EDX, EDX INVOKE IoCompleteRequest, ECX, EDX POP EAX ;return with EAX=STATUS_? RET Dispatch ENDP voila pour la routine de dispatch normale....Donc maintenant vous pouvez creer vos propres KMD et vous amuser :) Je vais vous donner maintenant 2-3 trucs propres a NT :) 1-> Imaginez que vous vouliez patcher grace a votre KMD certains programmes...Normalement vu qu'on est en Ring0 y ne devrait pas avoir de probleme Vous vous souvenez surement que sous Win9X on pouvait ecrire 'partout'....Bon si vous essayez ca vous risquez de rebooter assez souvent donc je vais vous l'eviter en vous donnant 'le truc'...Le probleme c'est que dans le CR0 (control register) le bit 16 est enable ce qui fait que lorsque vous essayez d'ecrire dans un page protegee en ecriture que vous soyez en ring0 ou non vous vous prenez une page fault en pleine figure...Faut donc disable ce bit :) Voila 2 ptites macros que j'ai codee pour vous faciliter tout ca :) Voila pour l'explication dans la doc d'intel: WP Write Protect (bit 16 of CR0). Inhibits supervisor-level procedures from writing into user-level read-only pages when set; allows supervisor-level procedures to write into user-level read-only pages when clear. This flag facilitates implementation of the copy-on- write method of creating a new process (forking) used by operating systems such as UNIX*. EnableWrite MACRO PUSH EAX MOV EAX,CR0 AND EAX,11111111111111101111111111111111b ;on clear le bit 16 du cr0 MOV CR0,EAX POP EAX ENDM DisableWrite MACRO PUSH EAX MOV EAX,CR0 OR EAX,NOT 11111111111111101111111111111111b ;on enable le bit 16 MOV CR0,EAX POP EAX ENDM 2-> Maintenant supposons que vous vouliez hooker certaines fonctions comme createfilea...Une methode 'barbare' consisterait a patcher directo la fonction initiale pour qu'elle vous envoit vers votre propre routine...Mais il existe une methode plus souple pour parvenir a vos fins :) NT utilise un system d'NTCall qui permettent d'utiliser des routines en ring0 via une application en Ring3...Le mecanisme est le suivant MOV EAX,NTCall_Number LEA EDX,Param INT 02Eh Bon sans vous montrer le listing de l'int 2Eh je vous dis qu'elle recherche dans une table le dword correspondant au NTCall_Number puis saute ensuite vers cette addresse en mettant sur la pile les parametres passe par EDX... Donc pour hooker par exemple CreateFileA on regarde un peu le code du kernel32 et dans CreatefileW on trouve un call ntdll!NTCreateFile et cette fonction nous fait : mov eax,20h lea edx,[esp+4] int 02eh Hehe un NTCall il nous suffit donc de modifier le dword dans la table correspondant au NTCall_Number 020h pour nous diriger vers notre new routine :)) Voila le code HookNtCreatefile: PUSHA MOV EAX, KeServiceDescriptorTable ;L'offset ou on pourra trouver l'addresse de la table dont je vous ai parle MOV EBX,020h ;Le numero du DWORD MOV EAX, DWORD ptr [EAX] ;on catche l'addresse de la table :) MOV EDX, DWORD ptr [EBX*4+EAX] ;EDX = addresse de l'ancienne fonction NTCreateFile MOV OrigNTCreateFile, EDX ;On sauvegarde MOV DWORD ptr [EBX*4+EAX], OFFSET HookedNTCreatefile ;on pose notre nouvelle fonction POPA XOR EDX,EDX XOR EAX,EAX RET UnHookNtCreatefile: PUSHA MOV EAX, KeServiceDescriptorTable MOV EBX,020h MOV EAX, DWORD ptr [EAX] ;pareil que plus haut mais dans l'autre sens MOV EDX, OrigNTCreateFile MOV DWORD ptr [EAX+EBX*4], EDX ;on restaure la fonction originale POPA XOR EAX,EAX XOR EDX,EDX RET Et hop vous avez hooke la fonction NTCreateFile :) en faisant NTCALL sous NTICE vous verrez toutes les fonctions differentes que vous pouvez hooker par cette methode c'est assez impressionnant :)) En plus c'est vraiment du lowlevel ca... Bon voila pour cette fois j'espere que ce chtit texte vous a appris qqchose :) ++ Greetz to: Spath,ELiCZ,Christal,DXP,Dark Angel,Elraizer,Alsindor,Stone,spike,TaMaMBoLo,Frog's Print,Lucifer48 Shroom,ACiD BuRN,ArseniK,Iczelion,Nody,Fravia,TeeJi,Taiefoon Vous pouvez me joindre si vous avez des questions (ou si vous avez des sources asm a faire partager :)) pulsar_c@geocities.com UIN:13411849 Pulsar Fevrier 2000