samedi 29 mars 2008

ph03nix et l'object manager.

Bonjour à tous, cette semaine j’ai décidé de me pencher sur les objects types initializer.

Je surfais sur le blog de mon maître jedi quand je suis tombé face à face sur un article concernant ces « Object Type Initializer », il aborde alors le sujet en énumérant quelques applications possibles.

Rendre un processus inkillable fut mon premier objectif, je pris donc mon courage a deux mains et me mit à bosser le sujet.

Il existe sous windows un "sous-système" qui a pour rôle de gerer les objects. L'object manager souvent abrégé "ObjMgr", est un système qui va gérer les ressources de windows. Ce que je désigne par le nom de “resource” peut être : un processus, un device, un driver..



Tout ces objects sont constitués de la même façon. Ils commencent d’abord par un header (OBJECT_HEADER) et sont suivit d'un body qui change en function du type d’object, EPROCESS pour un process, FILE_OBJECT pour un fichier ainsi de suite.

L'object manager à donc pour rôle de fournir à l’utilisateur une interface pour manipuler les différentes resources du noyau, cette interface étant principalement basée sur les handles.



Chaque object posséde une structure de type OBECT_TYPE_INITIALIZER qui est identique pour tout les objects de même type .Je décide donc de sortir le kd pour me renseigner un peu plus sur cette structure.

D’abord j’utilise la commande !process du kd. Je cite :


Syntax in Windows XP and later:
!process [/s Session] [/m Module] [Process [Flags]]
!process [/s Session] [/m Module] 0 Flags ImageName

[..]
Process
Specifies the hexadecimal address or the process ID of the process on the target computer.
The value of Process determines whether the !process extension displays a process address or a process ID . If Process is -1 in Windows NT 4.0 or is omitted in any version of Windows, the debugger displays data only about the current system process. If Process is 0 and ImageName is omitted, the debugger displays information about all active processes.

Flags
Specifies the level of detail to display. Flags can be any combination of the following bits. If Flags is 0, only a minimal amount of information is displayed. The default varies according to the version of Windows and the value of Process. In Windows NT 4.0, the default is 0x3 if Process is omitted or if Process is 0; otherwise, the default is 0xF. In Windows 2000, the default is 0x3 if Process is omitted or if Process is 0 and ImageFile is omitted; otherwise, the default is 0xF. In Windows XP and later, the default is 0x3 if Process is omitted or if Process is either 0 or -1; otherwise, the default is 0xF.

Bit 0 (0x1)
Displays time and priority statistics.

Bit 1 (0x2)
Displays a list of threads and events associated with the process, and their wait states.

Bit 2 (0x4)
Displays a list of threads associated with the process. If this is included without Bit 1 (0x2), each thread is displayed on a single line. If this is included along with Bit 1, each thread is displayed with a stack trace.

Bit 3 (0x8)
(Windows XP and later) Displays the return address, the stack pointer, and (on Itanium-based systems) the bsp register value for each function. The display of function arguments is suppressed.

Bit 4 (0x10)
(Windows XP and later) Sets the process context equal to the specified process for the duration of this command. This results in a more accurate display of thread stacks. Because this flag is equivalent to using .process /p /r for the specified process, any existing user-mode module list will be discarded. If Process is zero, the debugger displays all processes, and the process context is changed for each one. If you are only displaying a single process and its user-mode state has already been refreshed (for example, with .process /p /r), it is not necessary to use this flag. This flag is only effective when used with Bit 0 (0x1).

Me voilà partis.

kd> !process 0 0
**** NT ACTIVE PROCESS DUMP ****
PROCESS 817cc7c0 SessionId: none Cid: 0004 Peb: 00000000 ParentCid: 0000
DirBase: 00039000 ObjectTable: e1001cb0 HandleCount: 204.
Image: System

PROCESS 8160b698 SessionId: none Cid: 0228 Peb: 7ffdc000 ParentCid: 0004
DirBase: 0335b000 ObjectTable: e12feac0 HandleCount: 21.
Image: smss.exe

PROCESS 817e98f0 SessionId: 0 Cid: 0264 Peb: 7ffdf000 ParentCid: 0228
DirBase: 0440b000 ObjectTable: e13f8c08 HandleCount: 267.
Image: csrss.exe

PROCESS 815de5e0 SessionId: 0 Cid: 027c Peb: 7ffdb000 ParentCid: 0228
DirBase: 04511000 ObjectTable: e1440eb8 HandleCount: 251.
Image: winlogon.exe

PROCESS 815b8020 SessionId: 0 Cid: 02a8 Peb: 7ffde000 ParentCid: 027c
DirBase: 04e53000 ObjectTable: e14da758 HandleCount: 240.
Image: services.exe

PROCESS 815b4020 SessionId: 0 Cid: 02b4 Peb: 7ffd5000 ParentCid: 027c
DirBase: 04ef0000 ObjectTable: e1512ee0 HandleCount: 273.
Image: lsass.exe

PROCESS 8159c020 SessionId: 0 Cid: 0350 Peb: 7ffd4000 ParentCid: 02a8
DirBase: 0586d000 ObjectTable: e15371a8 HandleCount: 209.
Image: svchost.exe

PROCESS 8158ebd8 SessionId: 0 Cid: 03a4 Peb: 7ffd9000 ParentCid: 02a8
DirBase: 05be1000 ObjectTable: e1567690 HandleCount: 218.
Image: svchost.exe

PROCESS 8157d1b0 SessionId: 0 Cid: 0408 Peb: 7ffdc000 ParentCid: 02a8
DirBase: 06467000 ObjectTable: e14277b8 HandleCount: 774.
Image: svchost.exe

PROCESS 81571968 SessionId: 0 Cid: 0458 Peb: 7ffd7000 ParentCid: 02a8
DirBase: 06ac0000 ObjectTable: e14d7ba8 HandleCount: 55.
Image: svchost.exe

PROCESS 81562a08 SessionId: 0 Cid: 04b4 Peb: 7ffde000 ParentCid: 02a8
DirBase: 06aa5000 ObjectTable: e15ab910 HandleCount: 108.
Image: spoolsv.exe

PROCESS 8152eda0 SessionId: 0 Cid: 05b4 Peb: 7ffde000 ParentCid: 058c
DirBase: 097c9000 ObjectTable: e1abb258 HandleCount: 380.
Image: explorer.exe

PROCESS 81525928 SessionId: 0 Cid: 0638 Peb: 7ffd6000 ParentCid: 05b4
DirBase: 0ad0c000 ObjectTable: e1b763f0 HandleCount: 36.
Image: VMwareTray.exe

PROCESS 81512300 SessionId: 0 Cid: 0648 Peb: 7ffd4000 ParentCid: 05b4
DirBase: 0b018000 ObjectTable: e15ed1a0 HandleCount: 73.
Image: VMwareUser.exe

PROCESS 8150b3e8 SessionId: 0 Cid: 0650 Peb: 7ffd7000 ParentCid: 05b4
DirBase: 0b232000 ObjectTable: e15eb6a8 HandleCount: 69.
Image: ctfmon.exe

PROCESS 81509ad0 SessionId: 0 Cid: 0660 Peb: 7ffdc000 ParentCid: 05b4
DirBase: 0b3b8000 ObjectTable: e15f3830 HandleCount: 30.
Image: LClock.exe

PROCESS 814f3540 SessionId: 0 Cid: 06b4 Peb: 7ffde000 ParentCid: 02a8
DirBase: 0bc5f000 ObjectTable: e1ba3648 HandleCount: 42.
Image: VMwareService.exe

PROCESS 814ab8d8 SessionId: 0 Cid: 00b4 Peb: 7ffde000 ParentCid: 02a8
DirBase: 0cfb3000 ObjectTable: e1b74bb0 HandleCount: 106.
Image: alg.exe

PROCESS 8149b668 SessionId: 0 Cid: 06a8 Peb: 7ffdc000 ParentCid: 05b4
DirBase: 0906c000 ObjectTable: e1528008 HandleCount: 88.
Image: OSRLOADER.exe

PROCESS 8156f740 SessionId: 0 Cid: 031c Peb: 7ffdd000 ParentCid: 05b4
DirBase: 072b0000 ObjectTable: e10d49d0 HandleCount: 64.
Image: Dbgview.exe

PROCESS 8149b020 SessionId: 0 Cid: 0400 Peb: 7ffdb000 ParentCid: 05b4
DirBase: 08b93000 ObjectTable: e1618448 HandleCount: 75.
Image: taskmgr.exe


Ensuite j’utilise la commande !object.


The !object extension displays information about a system object.

!object Address
[...]
Address
If the first argument is a nonzero hexadecimal number, it specifies the hexadecimal address of the system object for which to display information.

On prend donc n'importe quel processus, car tous ces objects sont du même type, de plus la structure OBJECT_TYPE_INITIALIZER est globale à chaque type d'object.


kd> !object 817cc7c0
Object: 817cc7c0 Type: (817cce38) Process
ObjectHeader: 817cc7a8 (old version)
HandleCount: 2 PointerCount: 51

Nous avons donc l'adresse de ses headers.


kd> dt nt!_OBJECT_HEADER 817cc7a8
+0x000 PointerCount : 51
+0x004 HandleCount : 2
+0x004 NextToFree : 0x00000002
+0x008 Type : 0x817cce38 _OBJECT_TYPE
+0x00c NameInfoOffset : 0 ''
+0x00d HandleInfoOffset : 0 ''
+0x00e QuotaInfoOffset : 0 ''
+0x00f Flags : 0x22 '"'
+0x010 ObjectCreateInfo : 0x80560c80 _OBJECT_CREATE_INFORMATION
+0x010 QuotaBlockCharged : 0x80560c80
+0x014 SecurityDescriptor : 0xe10017d5
+0x018 Body : _QUAD

A partir de cette structure nous pouvons 'jongler' dans les headers de l'object.

Nous avons son Body en +0x18, ici il s'agit d'un pointeur sur une structure de type EPROCESS.

Nous avons un pointeur sur une structure de type OBJECT_TYPE, celle qui nous intéresse s'y trouve.


kd> dt nt!_OBJECT_TYPE 0x817cce38
+0x000 Mutex : _ERESOURCE
+0x038 TypeList : _LIST_ENTRY [ 0x817cce70 - 0x817cce70 ]
+0x040 Name : _UNICODE_STRING "Process"
+0x048 DefaultObject : (null)
+0x04c Index : 5
+0x050 TotalNumberOfObjects : 0x15
+0x054 TotalNumberOfHandles : 0x4c
+0x058 HighWaterNumberOfObjects : 0x16
+0x05c HighWaterNumberOfHandles : 0x52
+0x060 TypeInfo : _OBJECT_TYPE_INITIALIZER
+0x0ac Key : 0x636f7250
+0x0b0 ObjectLocks : [4] _ERESOURCE

Nous voilà dans cette fameuse structure 'globale'.

On y reconnaît bien le nom du type d'object à savoir Process dans ce cas là.

Ne perdons pas de vue notre structure OBJECT_TYPE_INITIALIZER en +0x60, go !


kd> dt nt!_OBJECT_TYPE_INITIALIZER 0x817cce38+0x60
+0x000 Length : 0x4c
+0x002 UseDefaultObject : 0 ''
+0x003 CaseInsensitive : 0 ''
+0x004 InvalidAttributes : 0xb0
+0x008 GenericMapping : _GENERIC_MAPPING
+0x018 ValidAccessMask : 0x1f0fff
+0x01c SecurityRequired : 0x1 ''
+0x01d MaintainHandleCount : 0 ''
+0x01e MaintainTypeList : 0 ''
+0x020 PoolType : 0 ( NonPagedPool )
+0x024 DefaultPagedPoolCharge : 0x1000
+0x028 DefaultNonPagedPoolCharge : 0x290
+0x02c DumpProcedure : (null)
+0x030 OpenProcedure : (null)
+0x034 CloseProcedure : (null)
+0x038 DeleteProcedure : 0x8058a87d void nt!PspProcessDelete+0
+0x03c ParseProcedure : (null)
+0x040 SecurityProcedure : 0x8056a71e long nt!SeDefaultObjectMethod+0
+0x044 QueryNameProcedure : (null)
+0x048 OkayToCloseProcedure : (null)

Je me vois donc hooker la callback DeleteProcedure, en effectuant une sorte de trie des processus victimes de la fonction PspProcessDelete.

Le prototype cette fonction est le suivant :


VOID
PspProcessDelete( IN PVOID Object )


Il me suffisait donc de récupérer le nom du processus, de le comparer a celui que j'etais censé protégé du kill et donc de lancer, ou au contraire de ne pas lancer la fonction PspProcessDelete.

J'installe donc mon hook, ma condition mais....

Le processus se fait quand même killer..

Frustré je vais tenter de vous montrer pourquoi il m'est impossible de protégé d'un kill du processus en controlant la DeleteProcedure.


« Merci à windows pour avoir foutu mon post en l'air :) »


Pour les personnes qui voudraient tout de même rendre un processus inkillable, vous pouvez toujours allez hooker la SSDT par exemple. La raison pour laquelle mon hook n'a pas fonctionné est la suivante : Cette callback est _apparemment_ pas utilisé pour détruire l'object mais pour déférencer le processus des tables ( EPROCESS par exemple ). Je n'intervenais donc en aucun cas sur la suppression ou non du processus cible.


On pourrait, je pense, faire des petits trucs sympathiques en allant s'amuser à hooker les procedures dans d'autre type d'object.

Si on hookait la OpenProcedure d'un type File, on pourrait par exemple mettre en place une espèce de routine de traitement, histoire de « monitorer » à chaque ouverture de handle sur l'object.

En tous cas, je ne voudrais pas m'avancer en ce qui concerne ces exemples d'exploitations car comme la mienne elles pourraient être vouées à l'echec ... :(


Bref continuons un peu plus sur les objects.

Au sein de la structure de type OBJECT_TYPE_INITIALIZER on peut croiser plusieurs type de callback :


  • Open qui est appelé lors de la création/ouverture/copie d'un handle.

  • Close qui est appelé lors de la fermeture d'un handle.

  • Delete qui est appelé lors de la suppression d'un object pour le déréférencer.


Ces « méthodes » sont celles que j'ai pu rencontrer dans ma petite excursion.

Voilà les informations que j'ai pu récoltés sur l'object manager, si quelques personnes auraient menés des recherches en rapport avec celui-ci merci de me le faire savoir :).


A présent je vous propose mon code ( foireux certes ) de hook de la DeleteProcedure :



Et un petit lien venut tout droit du uninformed v8 :



Voilà c'est finis pour aujourd'hui, en espérant que le post plaira a certains malgrès l'echec de mon hook :/.

Cya!

PS : Un échange de liens vient d'être mise en place avec les noxistes ainsi qu'avec Ghosts In The Stack, je les ajoute donc à la blogrollz, bonne continuation à eux et merci à eux deux.

samedi 22 mars 2008

C4lim3r0.

« YOU FAILED, PLEASE RESTART THE ENGINE ».


Bonjour à tous, je vais aujourd'hui vous parlez d'une feature que microsoft nous met à disposition.

Il s'agit des « minifilters ».

Un minifilter permet de crée un Filter Device Object (FiDO) beacoup plus facilement. En effet cette fois ci c’est driver natif de Windows, fltmgr.sys, qui va se charger de placer un FiDO sur les devices qui nous intéressent. Lors de la création d’un minifilter les devices du driver fltmgr.sys vont se placer sur les différents devices filesystem puis faire passer les requêtes et résultats des IRP de ces devices à notre driver sous une forme plus aisément manipulable.

On peut donc choisir sur quels types d'IRPs opérer, sur quel device nous allons nous attachés. Tous le reste sera gérer et orchestrer par le FilterManager (FltMgr). C'est bien beau … mais trop pour être vrai !

Premièrement le minifilter doit s'installer par le biais d'un fichier .inf, et il est exécuté sous forme de service à cause du FilterManager, pas très furtif tout ca …


L'aventure est tout de même séduisante, une nouvelle feature à expérimenter, nous pourrions l'utilisé afin de cacher un dossier par exemple.Mais cela fais deux semaines que j'ai travaillé en me fixant ce but, et je dois l'avouer j'ai lamentablement échoué dans ma besogne. Je me suis donc rediriger vers un objectif plus simple.


Il s'agit d'empêcher l'accès à un dossier lorsque l'on va double cliquez sur le dossier dans l'explorer par exemple. Je compte donc sur vous pour exploitez ce petit article et allez plus loin dans l'utilisation de ce minifilter.

Passons par dessus, les échecs sont censés faire avancer ..

« Wait and see.. ».

J'ai décidé donc de programmer un file system minifilter.

Je vous expose la technique utilisé :

  • Nous créons le fichier .inf permettant d'installer notre minifilter. (Pour cela je vous laisse vous documentez sur la msdn et cie)

  • Notre driver doit s'enregistrer auprès du FilterManager par le biais de la fonction FltRegisterFilter().

L'on doit donc remplir les structures FLT_REGISTRATION :


typedef struct _FLT_REGISTRATION {

USHORT Size;

USHORT Version;

FLT_REGISTRATION_FLAGS Flags;

CONST FLT_CONTEXT_REGISTRATION *ContextRegistration;

CONST FLT_OPERATION_REGISTRATION *OperationRegistration;

PFLT_FILTER_UNLOAD_CALLBACK FilterUnloadCallback;

PFLT_INSTANCE_SETUP_CALLBACK InstanceSetupCallback;

PFLT_INSTANCE_QUERY_TEARDOWN_CALLBACK InstanceQueryTeardownCallback;

PFLT_INSTANCE_TEARDOWN_CALLBACK InstanceTeardownStartCallback;

PFLT_INSTANCE_TEARDOWN_CALLBACK InstanceTeardownCompleteCallback;

PFLT_GENERATE_FILE_NAME GenerateFileNameCallback;

PFLT_NORMALIZE_NAME_COMPONENT NormalizeNameComponentCallback;

PFLT_NORMALIZE_CONTEXT_CLEANUP NormalizeContextCleanupCallback;

#if FLT_MGR_LONGHORN

PFLT_TRANSACTION_NOTIFICATION_CALLBACK TransactionNotificationCallback;

PFLT_NORMALIZE_NAME_COMPONENT_EX NormalizeNameComponentExCallback;

#endif // FLT_MGR_LONGHORN

} FLT_REGISTRATION, *PFLT_REGISTRATION;


ainsi que FLT_OPERATION_REGISTRATION :


typedef struct _FLT_OPERATION_REGISTRATION {

UCHAR MajorFunction;

FLT_OPERATION_REGISTRATION_FLAGS Flags;

PFLT_PRE_OPERATION_CALLBACK PreOperation;

PFLT_POST_OPERATION_CALLBACK PostOperation;

PVOID Reserved1;

} FLT_OPERATION_REGISTRATION, *PFLT_OPERATION_REGISTRATION;


A présent il nous faut élaborer les fonctions handler par la structure FLT_OPERATION_REGISTRATION.

Je vous laisse méditer le code pour cela.


Trip in da Minifilter.


On va tenter de savoir comment fonctionne un peu plus cette feature.


kd> !drvobj \FileSystem\C4lim3r0

Driver object (8152e670) is for:

\FileSystem\C4lim3r0

Driver Extension List: (id , addr)


Device Object list:


kd> !drvobj \FileSystem\FltMgr

Driver object (8179b428) is for:

\FileSystem\FltMgr

Driver Extension List: (id , addr)


Device Object list:

8148ceb0 8148d220 8148d390 8148d4c8

8148d748 8148dcc0 8179aa60 8179af18


kd> !devobj 8148ceb0

Device object (8148ceb0) is for:

\FileSystem\FltMgr DriverObject 8179b428

Current Irp 00000000 RefCount 0 Type 00000003 Flags 00000010

DevExt 8148cf68 DevObjExt 8148cfd0

ExtensionFlags (0000000000)

AttachedTo (Lower) 817eb0d8 \FileSystem\RAW

Device queue is not busy.


kd> !devobj 8148d220

Device object (8148d220) is for:

\FileSystem\FltMgr DriverObject 8179b428

Current Irp 00000000 RefCount 0 Type 00000008 Flags 00000010

DevExt 8148d2d8 DevObjExt 8148d340

ExtensionFlags (0000000000)

AttachedTo (Lower) 817eb1f0 \FileSystem\RAW

Device queue is not busy.


kd> !devobj 8148d390

Device object (8148d390) is for:

\FileSystem\FltMgr DriverObject 8179b428

Current Irp 00000000 RefCount 0 Type 00000008 Flags 00000000

DevExt 8148d448 DevObjExt 8148d478

ExtensionFlags (0000000000)

AttachedTo (Lower) 817307e8 \FileSystem\sr

Device queue is not busy.


kd> !devobj 8148d4c8

Device object (8148d4c8) is for:

\FileSystem\FltMgr DriverObject 8179b428

Current Irp 00000000 RefCount 0 Type 00000008 Flags 00000000

DevExt 8148d580 DevObjExt 8148d5d8

ExtensionFlags (0000000000)

AttachedTo (Lower) 817619b8 \FileSystem\sr

Device queue is not busy.


kd> !devobj 8148d748

Device object (8148d748) is for:

\FileSystem\FltMgr DriverObject 8179b428

Current Irp 00000000 RefCount 0 Type 00000003 Flags 00000000

DevExt 8148d800 DevObjExt 8148d858

ExtensionFlags (0000000000)

AttachedTo (Lower) 81600140 \FileSystem\Cdfs

Device queue is not busy.


kd> !devobj 8148dcc0

Device object (8148dcc0) is for:

\FileSystem\FltMgr DriverObject 8179b428

Current Irp 00000000 RefCount 0 Type 00000014 Flags 00000000

DevExt 8148dd78 DevObjExt 8148dda8

ExtensionFlags (0000000000)

AttachedTo (Lower) 8160c030 \FileSystem\MRxSmb

Device queue is not busy.


kd> !devobj 8179aa60

Device object (8179aa60) is for:

FltMgrMsg \FileSystem\FltMgr DriverObject 8179b428

Current Irp 00000000 RefCount 0 Type 00000040 Flags 00000040

Dacl e12a0634 DevExt 00000000 DevObjExt 8179ab18

ExtensionFlags (0000000000)

Device queue is not busy.


kd> !devobj 8179af18

Device object (8179af18) is for:

FltMgr \FileSystem\FltMgr DriverObject 8179b428

Current Irp 00000000 RefCount 0 Type 00000008 Flags 00000040

Dacl e12b1d1c DevExt 00000000 DevObjExt 8179afd0

ExtensionFlags (0000000000)

Device queue is not busy.


Le filter manager va donc créer des FiDOs dans le but d'intercepter les IRPs destinées au driver gérant le filesystem (voir dump kd).



En parcourant le log nous voyons bien que des devices sont attachés aux autres filesystem devices.

A présent nous allons poser un breakpoint sur la routine qui gere notre IRP au niveau du driver \FileSystem\Ntfs.

Pour cela nous allons utiliser le kd et là fonction « !drvobj DriverObject [Flag]»

Je cite :


The !drvobj extension displays detailed information about a DRIVER_OBJECT.

[..]

DriverObject

Specifies the driver object. In Windows NT 4.0, this must be the hexadecimal address of the DRIVER_OBJECT structure. In Windows 2000 and later, this can be the hexadecimal address of the DRIVER_OBJECT structure or the name of the driver.


Flags

(Windows 2000 and later) Can be any combination of the following bits. (The default is 0x01.)


Bit 0 (0x1)

Causes the display to include device objects owned by the driver.


Bit 1 (0x2)

Causes the display to include entry points for the driver's dispatch routines.


Bit 2 (0x4)

Lists with detailed information the device objects owned by the driver (requires bit 0).


Nous allons donc énumérez les adresses des « dispatch routines » gérant les différentes IRPs.


kd> !drvobj \FileSystem\Ntfs 2

Driver object (817a3308) is for:

\FileSystem\Ntfs

DriverEntry: f9924184 Ntfs

DriverStartIo: 00000000

DriverUnload: 00000000

AddDevice: 00000000


Dispatch routines:

[00] IRP_MJ_CREATE f98c4c01 Ntfs+0x25c01

[01] IRP_MJ_CREATE_NAMED_PIPE 805025e4 nt!IopInvalidDeviceRequest

[02] IRP_MJ_CLOSE f98c40ea Ntfs+0x250ea

[03] IRP_MJ_READ f98a1f3b Ntfs+0x2f3b

[04] IRP_MJ_WRITE f98a0b57 Ntfs+0x1b57

[05] IRP_MJ_QUERY_INFORMATION f98c52b9 Ntfs+0x262b9

[06] IRP_MJ_SET_INFORMATION f98a2618 Ntfs+0x3618

[07] IRP_MJ_QUERY_EA f98c52b9 Ntfs+0x262b9

[08] IRP_MJ_SET_EA f98c52b9 Ntfs+0x262b9

[09] IRP_MJ_FLUSH_BUFFERS f98deec8 Ntfs+0x3fec8

[0a] IRP_MJ_QUERY_VOLUME_INFORMATION f98c5404 Ntfs+0x26404

[0b] IRP_MJ_SET_VOLUME_INFORMATION f98c5404 Ntfs+0x26404

[0c] IRP_MJ_DIRECTORY_CONTROL f98c6fbd Ntfs+0x27fbd

[0d] IRP_MJ_FILE_SYSTEM_CONTROL f98c9758 Ntfs+0x2a758

[0e] IRP_MJ_DEVICE_CONTROL f98c5404 Ntfs+0x26404

[0f] IRP_MJ_INTERNAL_DEVICE_CONTROL 805025e4 nt!IopInvalidDeviceRequest

[10] IRP_MJ_SHUTDOWN f98b35af Ntfs+0x145af

[11] IRP_MJ_LOCK_CONTROL f9918aa3 Ntfs+0x79aa3

[12] IRP_MJ_CLEANUP f98c4ab8 Ntfs+0x25ab8

[13] IRP_MJ_CREATE_MAILSLOT 805025e4 nt!IopInvalidDeviceRequest

[14] IRP_MJ_QUERY_SECURITY f98c5404 Ntfs+0x26404

[15] IRP_MJ_SET_SECURITY f98c5404 Ntfs+0x26404

[16] IRP_MJ_POWER 805025e4 nt!IopInvalidDeviceRequest

[17] IRP_MJ_SYSTEM_CONTROL 805025e4 nt!IopInvalidDeviceRequest

[18] IRP_MJ_DEVICE_CHANGE 805025e4 nt!IopInvalidDeviceRequest

[19] IRP_MJ_QUERY_QUOTA f98c52b9 Ntfs+0x262b9

[1a] IRP_MJ_SET_QUOTA f98c52b9 Ntfs+0x262b9

[1b] IRP_MJ_PNP f98e17f0 Ntfs+0x427f0


Fast I/O routines:

FastIoCheckIfPossible f98d8eda Ntfs+0x39eda

FastIoRead f98bfb57 Ntfs+0x20b57

FastIoWrite f98de448 Ntfs+0x3f448

FastIoQueryBasicInfo f98c548e Ntfs+0x2648e

FastIoQueryStandardInfo f98c3f7e Ntfs+0x24f7e

FastIoLock f98df0f2 Ntfs+0x400f2

FastIoUnlockSingle f98df1f8 Ntfs+0x401f8

FastIoUnlockAll f99186ae Ntfs+0x796ae

FastIoUnlockAllByKey f99187f3 Ntfs+0x797f3

AcquireFileForNtCreateSection f98bf83a Ntfs+0x2083a

ReleaseFileForNtCreateSection f98bf881 Ntfs+0x20881

FastIoQueryNetworkOpenInfo f9906e1d Ntfs+0x67e1d

AcquireForModWrite f98cba10 Ntfs+0x2ca10

MdlRead f9906f31 Ntfs+0x67f31

MdlReadComplete 8052bb18 nt!FsRtlMdlReadCompleteDev

PrepareMdlWrite f99072ab Ntfs+0x682ab

MdlWriteComplete 80611143 nt!FsRtlMdlWriteCompleteDev

FastIoQueryOpen f98c3db8 Ntfs+0x24db8

AcquireForCcFlush f98bf6e2 Ntfs+0x206e2

ReleaseForCcFlush f98bf708 Ntfs+0x20708


Puis poser un breakpoint afin de pouvoir regarder un peu les IRPs du type IRP_MJ_DIRECTORY_CONTROL, celle que l'on contrôle au seins de notre minifilter.


kd> bp f98c6fbd


On pose un breakpoint sur la routine de notre driver qui va corrompre le IO_STATUS_BLOCK de l'irp.


kd> bp C4lim3r0!ApresDirectoryControl


On relance la vm.

kd> g


Normalement une fois query le dossier, on devrait breakpoint sur le driver Ntfs afin de visionner le status de l'irp, et ensuite notre minifilter devrait « intercepter » celle-ci et là nous tracerons afin d'arriver jusqu'au moment où l'on va modifier le status, nous afficherons ensuite le statut.


Breakpoint 0 hit

Ntfs+0x27fbd:

f98c6fbd 684c010000 push 14Ch


Op nous y voilà, nous affichons la call stack avec kv, pour pouvoir retrouver un pointeur sur une structure IRP, n'oublions pas que le prototype d'une dispatch routine est de cette forme :


NTSTATUS DispatchRoutines(PDEVICE_OBJECT pDeviceObject,PIRP pIrp)


Nous pouvons donc retrouver ce pointeur en dernier argument pusher sur la stack.

kd> kv

ChildEBP RetAddr Args to Child

WARNING: Stack unwind information not available. Following frames may be wrong.

f7d10c7c 804e3d77 81794880 815ad818 815ad818 Ntfs+0x27fbd

f7d10cf8 8056a9ab f7d10d64 0148de30 80574dad nt!IopfCallDriver+0x31 (FPO: [0,0,0])

f7d10cb0 f995906b f7d10cd0 8150d490 00000000 nt!IopSynchronousServiceTail+0x60 (FPO: [Non-Fpo])

f7d10ce8 804e3d77 8150d490 815ad818 807112d0 fltMgr!FltGetIrpName+0x12ad

f7d10cf8 8056a9ab f7d10d64 0148de30 80574dad nt!IopfCallDriver+0x31 (FPO: [0,0,0])

f7d10d0c 80574e0a 8150d490 815ad818 815117a8 nt!IopSynchronousServiceTail+0x60 (FPO: [Non-Fpo])

f7d10d30 804df06b 00000230 00000000 00000000 nt!NtQueryDirectoryFile+0x5d (FPO: [Non-Fpo])

f7d10d30 7c91eb94 00000230 00000000 00000000 nt!KiFastCallEntry+0xf8 (FPO: [0,0] TrapFrame @ f7d10d64)

0148e108 7c9f8afd 0148e3b0 00000000 023e5cb4 0x7c91eb94

0148e12c 7c9f8a97 0148e3b0 023e5cb4 023e5aa4 0x7c9f8afd

0148e380 7c9fa996 000400e8 00000000 0148e3b0 0x7c9f8a97

0148e5d0 7c9fa870 023f6380 023f6368 0148e5f8 0x7c9fa996

0148e5e0 7c9fab6d 023f6578 000400e8 000000e0 0x7c9fa870

0148e5f8 7c9ff03d 023f6588 000400e8 000000e0 0x7c9fab6d

0148e62c 7c9ffa3e 000400e8 0012687c 00126860 0x7c9ff03d

0148e680 7e22d8f1 00000006 00000000 00126860 0x7c9ffa3e

0148e72c 7e22ade9 0011d8f8 00126860 023e54f0 0x7e22d8f1

0148e754 75f18518 001264d4 023e54f0 001864d0 0x7e22ade9

0148e770 75f2c7ca 0011d8fc 023e54f0 001864d0 0x75f18518

0148e790 7e22b0b3 0011d8fc 023e54f0 001864d0 0x75f2c7ca


Nous avons notre pointeur utilisons la commande !irp.

kd> !irp 815ad818 1

Irp is active with 9 stacks 8 is current (= 0x815ad984)

No Mdl: No System Buffer: Thread 81593020: Irp stack trace.

Flags = 00000800

ThreadListEntry.Flink = 81593230

ThreadListEntry.Blink = 81593230

IoStatus.Status = 00000000

IoStatus.Information = 00000000

RequestorMode = 00000001

Cancel = 00

CancelIrql = 0

ApcEnvironment = 00

UserIosb = 0148de6c

UserEvent = 00000000

Overlay.AsynchronousParameters.UserApcRoutine = 00000000

Overlay.AsynchronousParameters.UserApcContext = 00000000

Overlay.AllocationSize = 00000000 - 00000000

CancelRoutine = 00000000

UserBuffer = 0148de9c

&Tail.Overlay.DeviceQueueEntry = 815ad858

Tail.Overlay.Thread = 81593020

Tail.Overlay.AuxiliaryBuffer = 814db890

Tail.Overlay.ListEntry.Flink = 00000000

Tail.Overlay.ListEntry.Blink = 00000000

Tail.Overlay.CurrentStackLocation = 815ad984

Tail.Overlay.OriginalFileObject = 815117a8

Tail.Apc = 00000000

Tail.CompletionKey = 00000000

cmd flg cl Device File Completion-Context

[ 0, 0] 0 0 00000000 00000000 00000000-00000000


Args: 00000000 00000000 00000000 00000000

[ 0, 0] 0 0 00000000 00000000 00000000-00000000


Args: 00000000 00000000 00000000 00000000

[ 0, 0] 0 0 00000000 00000000 00000000-00000000


Args: 00000000 00000000 00000000 00000000

[ 0, 0] 0 0 00000000 00000000 00000000-00000000


Args: 00000000 00000000 00000000 00000000

[ 0, 0] 0 0 00000000 00000000 00000000-00000000


Args: 00000000 00000000 00000000 00000000

[ 0, 0] 0 0 00000000 00000000 00000000-00000000


Args: 00000000 00000000 00000000 00000000

[ 0, 0] 0 0 00000000 00000000 00000000-00000000


Args: 00000000 00000000 00000000 00000000

>[ c, 1] 2 e0 81793020 815117a8 f99587de-815b9578 Success Error Cancel

\FileSystem\Ntfs fltMgr!FltGetIrpName

Args: 00000268 814db890 00000003 00000000

[ c, 1] 2 1 8150d490 815117a8 00000000-00000000 pending

\FileSystem\FltMgr

Args: 00000268 814db890 00000003 00000000



Nous avons bien un STATUS_SUCCESS dans le IoStatus.status.

On relance le kd pour breakpoint sur notre driver.


kd> g

Breakpoint 1 hit

C4lim3r0!ApresDirectoryControl:

fa161490 8bff mov edi,edi

kd> p

C4lim3r0!ApresDirectoryControl+0x8:

fa161498 68b01516fa push offset C4lim3r0! ?? ::FNODOBFM::`string' (fa1615b0)

kd> p

C4lim3r0!ApresDirectoryControl+0x17:

fa1614a7 8d4dfc lea ecx,[ebp-4]

kd> p

C4lim3r0!ApresDirectoryControl+0x29:

fa1614b9 8b45f4 mov eax,dword ptr [ebp-0Ch]

kd> p

C4lim3r0!ApresDirectoryControl+0x41:

fa1614d1 8b45fc mov eax,dword ptr [ebp-4]

kd> p
FileName : '\Device\HarddiskVolume1\C4lim3r0__.'C4lim3r0!ApresDirectoryControl+0x55:
fa1614e5 8b4d08 mov ecx,dword ptr [ebp+8]
kd> p
C4lim3r0!ApresDirectoryControl+0x5f:
fa1614ef 8b5508 mov edx,dword ptr [ebp+8]
kd> p
C4lim3r0!ApresDirectoryControl+0x69:
fa1614f9 33c0 xor eax,eax

On trace avec F10 pour arriver après la modification du status, on matte la callstack pour retrouver un pointeur sur une structure PFLT_CALLBACK_DATA.


typedef struct _FLT_CALLBACK_DATA {
FLT_CALLBACK_DATA_FLAGS Flags;
PETHREAD CONST Thread;
PFLT_IO_PARAMETER_BLOCK CONST Iopb;
IO_STATUS_BLOCK IoStatus;
struct _FLT_TAG_DATA_BUFFER *TagData;
union {
struct {
LIST_ENTRY QueueLinks;
PVOID QueueContext[2];
};
PVOID FilterContext[4];
};
KPROCESSOR_MODE RequestorMode;
} FLT_CALLBACK_DATA, *PFLT_CALLBACK_DATA;

typedef struct _IO_STATUS_BLOCK {
union {
NTSTATUS Status;
PVOID Pointer;
};
ULONG_PTR Information;
} IO_STATUS_BLOCK, *PIO_STATUS_BLOCK;

Let's go


kd> kv
ChildEBP RetAddr Args to Child
f7d107d8 f9955ef3 815b95d4 f7d107fc 00000000 C4lim3r0!ApresDirectoryControl+0x41 (FPO: [Non-Fpo]) (CONV: stdcall) [c:\k3rn3l\c4lim3r0.c @ 79]
WARNING: Stack unwind information not available. Following frames may be wrong.
f7d10840 f9958338 005b9578 815ad987 815b9578 fltMgr!FltRequestOperationStatusCallback+0x5bd
f7d10854 f9958867 815b9578 815ad818 f7d10894 fltMgr!FltGetIrpName+0x57a
f7d10864 804e42cc 8150d490 815ad818 815b9578 fltMgr!FltGetIrpName+0xaa9
f7d10894 f989f6bb 00000000 e117ceb8 f7d10ab8 nt!IopfCompleteRequest+0xa2 (FPO: [Non-Fpo])
f7d108a4 f98c8187 f7d10b08 815ad818 00000000 Ntfs+0x6bb
f7d10ab8 f98c70e8 f7d10b08 815ad818 81793100 Ntfs+0x29187
f7d10aec f98c7053 f7d10b08 e117cd20 00000000 Ntfs+0x280e8
f7d10c64 804e3d77 81793020 815ad818 817a3728 Ntfs+0x28053
f7d10cf8 8056a9ab f7d10d64 0148de30 80574dad nt!IopfCallDriver+0x31 (FPO: [0,0,0])
f7d10c7c 804e3d77 81794880 815ad818 815ad818 nt!IopSynchronousServiceTail+0x60 (FPO: [Non-Fpo])
f7d10cf8 8056a9ab f7d10d64 0148de30 80574dad nt!IopfCallDriver+0x31 (FPO: [0,0,0])
f7d10cb0 f995906b f7d10cd0 8150d490 00000000 nt!IopSynchronousServiceTail+0x60 (FPO: [Non-Fpo])
f7d10ce8 804e3d77 8150d490 815ad818 807112d0 fltMgr!FltGetIrpName+0x12ad
f7d10cf8 8056a9ab f7d10d64 0148de30 80574dad nt!IopfCallDriver+0x31 (FPO: [0,0,0])
f7d10d0c 80574e0a 8150d490 815ad818 815117a8 nt!IopSynchronousServiceTail+0x60 (FPO: [Non-Fpo])
f7d10d30 804df06b 00000230 00000000 00000000 nt!NtQueryDirectoryFile+0x5d (FPO: [Non-Fpo])
f7d10d30 7c91eb94 00000230 00000000 00000000 nt!KiFastCallEntry+0xf8 (FPO: [0,0] TrapFrame @ f7d10d64)
0148e108 7c9f8afd 0148e3b0 00000000 023e5cb4 0x7c91eb94
0148e12c 7c9f8a97 0148e3b0 023e5cb4 023e5aa4 0x7c9f8afd

Nous avons notre pointeur nous allons afficher afficher la mémoire avec la commande dd.


kd> dd 815b95d4
815b95d4 00080001 81593020 815b9644 c0000055
815b95e4 00000000 00000000 00000000 00000000
815b95f4 00000000 00000000 00000001 00000800
815b9604 0002010c 815117a8 8158fe78 00000268
815b9614 814db890 00000003 00000000 0148de9c
815b9624 00000000 00000000 815b9578 8158ffbc
815b9634 815b9944 8151fea4 815b9940 00000000
815b9644 00000800 0002010c 815117a8 8158fe78
kd> bc 0
kd> bc 1
kd> bl

Compte tenu du prototype de la fonction nous pouvons constater que notre IoStatus.status est a présent « c0000055 » il a bien été modifié.



Enfin bon voilà !

C'est finis pour aujourd'hui en espérant que les logs du kd vous permettrons de faire des petites recherches c'est plutot sympathique je trouve.


Voici les liens pour les sources du minifilter :

-C4lim3r0's inf file.

-C4lim3r0.c.

Voilà bonne après midi à vous, cya.


PS: Je viens d'ajouter le site de la communauté Spirit Of Hack (SOH) dans la blogrollz, n'hésiter pas a faire un tour :).

PS2: Voici l'arrivée du repository de Geo dans la blogrollz.

En tous les cas merci à vous et bonne continuation.

vendredi 7 mars 2008

Sur les traces du KLOG.

Bonjour à vous,
Je vous propose aujourd’hui ma petite contribution régulière.
Celle-ci traitera du principe du KLOG, un keylogger kernel programmé par Clandestiny.

Dans cet article, nous allons parler un peu du « comment le KLOG opère t-il ? » afin de nous coder un petit driver perso pour mettre en pratique les choses que l’on vient d’apprendre.

Je vous propose quelques outils pouvant être utile au cours du coding et de l’analyse du KLOG :
- DeviceTree, peut être utile pour observer les devices créer par les drivers par exemple.
- IrpTracker, un outil permettant de « tracker » les IRPs reçus par un device.

Les outils en main, nous pouvons nous attaquer au fonctionnement de l’engin.

Le KLOG dans la place

Vous êtes maintenant préparer à suivre la suite de l’article.
Pour mener à bien son fonctionnement le KLOG va attacher un filter device ( FiDO ) au dessus du device KeyboardClass0 créer par le driver Kbdclass. Le driver KbdClass à pour rôle de fournir une interface entre le sytème et le driver physique :

( Je cite )
The HID class driver does the following:
Provides and manages the upper-level interface that kernel-mode drivers and user-mode applications use to access the HID collections that an input device supports.
The HID class driver transparently manages and routes all communication between upper-level drivers and applications and the underlying input devices that support HID collections. It manages the different data protocols used by different input devices and input queues that support more than one open file on the same HID collection. (!!)
The upper-level interface to HID collections consists of the HID class driver IOCTLs, the HIDClass support routines, and the HIDClass structures.
Communicates with a HID minidriver by calling the minidriver's standard driver routines — see Communicating with a HID Minidriver.
Creates a functional device object (FDO) for HIDClass input devices enumerated by a lower-level bus or port driver.
For example, the HID class driver creates and manages the operations of an FDO that represents a USB HID device enumerated by the system-supplied USB driver stack.
Provides the functionality of a bus driver for the child devices (HID collections) supported by an underlying input device.
The HID class driver creates a physical device object (PDO) for each HID collection supported by an input device and manges the collection's operation.
(juste pour informations)


Il faut aussi savoir que le device KeyboardClass0 est attaché au device anonyme du driver i8042prt. Le driver i8042prt est de type PDO (Pysical Device Object), il gère la gestion de la souris et du clavier. Le HID driver va crée un FDO (Functional Device Object) au dessus du PDO pour fournir une interface entre le sytème et le périphérique.





Le KeyboardClass1 est un clavier virtuel, il ne nous intéresse pas du tout.
Vu que tout le concept repose sur la device stack du driver, nous allons nous renseigner un peu plus sur celle-ci, sortons donc le kd.

kd> !devstack \device\keyboardclass0
!DevObj !DrvObj !DevExt ObjectName
> 816f53a0 \Driver\Kbdclass 816f5458 KeyboardClass0
816f5588 \Driver\i8042prt 816f5640
817d2618 \Driver\ACPI 817da2e8 00000043
!DevNode 81799948 :
DeviceInst is "ACPI\PNP0303\4&5289e18&0"
ServiceName is "i8042prt"
kd> !drvobj \Driver\Kbdclass 3
Driver object (816f5930) is for:
\Driver\Kbdclass
Driver Extension List: (id , addr)

Device Object list:
816d5030 816f53a0 q

DriverEntry: f9d0f610
DriverStartIo: 00000000
DriverUnload: 00000000
AddDevice: f9d0eb02

Dispatch routines:
[00] IRP_MJ_CREATE f9d0bdd8 +0xf9d0bdd8
[01] IRP_MJ_CREATE_NAMED_PIPE 805025e4 nt!IopInvalidDeviceRequest
[02] IRP_MJ_CLOSE f9d0bfe8 +0xf9d0bfe8
[03] IRP_MJ_READ f9d0cc82 +0xf9d0cc82
[04] IRP_MJ_WRITE 805025e4 nt!IopInvalidDeviceRequest
[05] IRP_MJ_QUERY_INFORMATION 805025e4 nt!IopInvalidDeviceRequest
[06] IRP_MJ_SET_INFORMATION 805025e4 nt!IopInvalidDeviceRequest
[07] IRP_MJ_QUERY_EA 805025e4 nt!IopInvalidDeviceRequest
[08] IRP_MJ_SET_EA 805025e4 nt!IopInvalidDeviceRequest
[09] IRP_MJ_FLUSH_BUFFERS f9d0bd50 +0xf9d0bd50
[0a] IRP_MJ_QUERY_VOLUME_INFORMATION 805025e4 nt!IopInvalidDeviceRequest
[0b] IRP_MJ_SET_VOLUME_INFORMATION 805025e4 nt!IopInvalidDeviceRequest
[0c] IRP_MJ_DIRECTORY_CONTROL 805025e4 nt!IopInvalidDeviceRequest
[0d] IRP_MJ_FILE_SYSTEM_CONTROL 805025e4 nt!IopInvalidDeviceRequest
[0e] IRP_MJ_DEVICE_CONTROL f9d0da44 +0xf9d0da44
[0f] IRP_MJ_INTERNAL_DEVICE_CONTROL f9d0d386 +0xf9d0d386
[10] IRP_MJ_SHUTDOWN 805025e4 nt!IopInvalidDeviceRequest
[11] IRP_MJ_LOCK_CONTROL 805025e4 nt!IopInvalidDeviceRequest
[12] IRP_MJ_CLEANUP f9d0bd0c +0xf9d0bd0c
[13] IRP_MJ_CREATE_MAILSLOT 805025e4 nt!IopInvalidDeviceRequest
[14] IRP_MJ_QUERY_SECURITY 805025e4 nt!IopInvalidDeviceRequest
[15] IRP_MJ_SET_SECURITY 805025e4 nt!IopInvalidDeviceRequest
[16] IRP_MJ_POWER f9d0e196 +0xf9d0e196
[17] IRP_MJ_SYSTEM_CONTROL f9d0d844 +0xf9d0d844
[18] IRP_MJ_DEVICE_CHANGE 805025e4 nt!IopInvalidDeviceRequest
[19] IRP_MJ_QUERY_QUOTA 805025e4 nt!IopInvalidDeviceRequest
[1a] IRP_MJ_SET_QUOTA 805025e4 nt!IopInvalidDeviceRequest
[1b] IRP_MJ_PNP f9d0c798 +0xf9d0c798

kd> !devobj 0x816d5030
Device object (816d5030) is for:
KeyboardClass1 \Driver\Kbdclass DriverObject 816f5930
Current Irp 00000000 RefCount 0 Type 0000000b Flags 00002044
Dacl e129e634 DevExt 816d50e8 DevObjExt 816d51c8
ExtensionFlags (0000000000)
AttachedTo (Lower) 816d41e0 \Driver\TermDD
Device queue is not busy.

kd> !devobj 0x816f53a0
Device object (816f53a0) is for:
KeyboardClass0 \Driver\Kbdclass DriverObject 816f5930
Current Irp 00000000 RefCount 0 Type 0000000b Flags 00002044
Dacl e129e634 DevExt 816f5458 DevObjExt 816f5538
ExtensionFlags (0000000000)
AttachedTo (Lower) 816f5588 \Driver\i8042prt
Device queue is not busy.

Nous avons donc nos renseignements sur la device stack, ces infos sont bien sur aussi visibles grâce au programme DeviceTree. Notre device placé au dessus du KeyboardClass0, va donc recevoir les IRPs avant lui.
C’est ici que tout se joue !

Nous allons mettre en place une « Completion Routine » qui sera appelé au retour de l’IRP, c’est-à-dire quand elle contiendra les informations ( les scancodes des touches ) délivré par le driver, le retour de l’IRP est provoqué par l’appel de la fonction IoCompleteRequest dans le driver KbdClass. Cette Completion routine va permettre de lire les IRPs et donc de récupérer les scancodes des touches.

Cependant les personnes qui ont déjà étudiés le KLOG, savent que la tache de les écrire n’est pas si facile. En effet la fonction permettant l’écriture dans le fichier tourne à un IRQL différent, comprenez que écriture dans un fichier demande au système d’être dans un état non-interrompu. Bref pour nous on s’arrête là afin de coder un petit truc personnalisé.Mais Clandestiny gère ce problème en créant un thread kernel tournant à l’IRQL nécessaire.

Je vous propose quelques schémas, les 2 premiers venus tout droit de mon imagination, et le dernier extrait du pdf fournis dans l’archive du KLOG :










Nous avons donc toutes les clés en main pour coder un petit driver .

Control your keyboard.

Au cours de cette partie, notre but va être non pas de lire, mais de modifier les scancodes des lettres, afin de contrôler les touches.Le driver va renvoyé les scancodes de façon a écrire « overclok » quelque soit les touches tapées.

Pour mener a bien notre projet, nous allons créer un device par le biais de la fonction IoCreateDevice(), puis l’attacher avec IoAttachDevice() sur \Device\KeyboardClass0.
Petite précision pour le IoCreateDevice(), nous allons utilisé un de ces paramètres afin de faire transiter une structure personnalisée. En effet nous devons garder à l’esprit que les IRP doivent être envoyées au driver KbdClass, pour cela il faut connaître l’adresse du device \Device\KeyboardClass0, l’I/O Manager fournit pour chaque device une structure personnalisé appelée DeviceExtension permettant au programmeur d’y ajouter des infos. Dans notre cas nous allons donc juste avoir un champ avec à pointeur sur le device KeyboardClass0.





Nous devons bien évidemment remplir le tableau MajorFunction pour handler des fonctions à appeler selon les IRPs reçus.
Celles intéressantes sont les IRP_MJ_READ.

Notre fonction qui sera appelée lors de la réception d’une telle IRP doit mettre en place la Completion Routine grâce à la fonction IoSetCompletionRoutine() puis nous « relayons » les IRPs au device d’en dessous.

En ce qui concerne notre la Completion Routine c’est en quelque sorte le cœur de notre driver, car en effet c’est ici que la modification ou la lecture des IRPs aura lieu.

Pour ma part j’ai choisis d’aller remplacer les scancodes des touches de manière a former le mot « overclok » lors de l’appuie sur les touches de votre clavier.

Un petit screenshot :





Je vous propose aussi de lire un article rédigé par Ivanlef0u sur sa tentative de modification du KLOG.
Il a modifié quelques petits trucs sur la version qu’il propose, à savoir le support des claviers français et le hidalgo du driver dans la PsLoadedModuleList.

Voici le lien :
- KLOG -> http://www.ivanlef0u.tuxfamily.org/?p=17.

A présent je vous propose mon petit code :
- OwnzYourKeyboard.c.

C’est finit pour aujourd’hui en espérant vous avoir divertis un petit peu, encore merci au personne qui m’ont aidé à la réalisation de cet article etc.

PS : Je tiens aussi à passer un petit coup de pub pour des amis.
Tout d'abord l'ouverture du site perso de shaka ou sevieron, un site internet rassemblant des écrits qui seront rédigés par lui même concernant de multiples domaines liés a l'informatique.
Ensuite l'ouverture de deux blogs de deux autres personnes que j'apprécie beaucoup, il s'agit de KPCR et de santabug.
En espérant que ces blogs et ce site seront tenus à jour par les auteurs, et que les articles apparaitront d'ici peu :).
Bonne chance à vous, voici les liens ajouter à la blogrollz :

- Shaka Web Site -> http://shaka.n0ne.org/.
- Santabug's blog -> http://santabug.blogspot.com/.
- KPCR's blog -> http://kpcr.blogspot.com/.

Cya.