#include <ntddk.h>

VOID Unload(IN PDRIVER_OBJECT DriverObject)
{
 __asm{
  cli           //Clear Interrupt
  push eax                  //save eax
  mov eax, cr0
  and eax,0xfffeffff  //11111111111111101111111111111111  즉 , WP 비트를 의도적으로 0으로 세트함.
  mov cr0, eax
  pop eax                   //restore eax
 }
 DbgPrint("Control Reg 0 WP Clear");



//  훅을  원래대로 돌려놓는 코드를 작성



 __asm{
  push eax           //save eax
  mov eax, cr0
  or eax, NOT 0xfffeffff     //00000000000000010000000000000000 WP 비트를 1로 세팅함.
  mov cr0, eax
  pop eax             //restore eax
  sti               //Set Interrupt
 }
 DbgPrint("Control Reg 0  WP Set");
}



NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject,
      IN PUNICODE_STRING RegistryPath)
{
 DriverObject->DriverUnload=Unload;
 __asm{
  cli
  push eax                  //save eax
  mov eax, cr0
  and eax,0xfffeffff  //11111111111111101111111111111111  즉 , WP 비트를 의도적으로 0으로 세트함.
  mov cr0, eax
  pop eax                   //restore eax
 }
 DbgPrint("Control Reg 0 WP Clear");



//원하는 Hooking Code 작성



 __asm{
  push eax           //save eax
  mov eax, cr0
  or eax, NOT 0xfffeffff     //00000000000000010000000000000000 WP 비트를 1로 세팅함.
  mov cr0, eax
  pop eax             //restore eax
  sti
 }
DbgPrint("Control Reg 0  WP Set");
 return STATUS_SUCCESS;
}


위 코드는 각종 블로그  , 인터넷 사이트 등에 알려진지 꽤 오래 된 코드이다.


보통 SSDT, SSDTShadow, KiFastCallEntry 등 에 접근하여 쓰기작업을 수행하고자 할때 ,  (후킹할 때)
먼저 CR0 레지스터의 Write Protection 비트에 접근하여, WP를 해제시켜주어야 한다.
해제시켜주지 않으면 , 공포의 Blue Screen Of Death 를 맛보게 될것이니...
왜냐면 SSDT 영역은 기본적으로 읽기전용 영역으로 지정되어져 있다.
그런데  WP비트를 해제시켜주지않고  , 거기에 쓰기 작업을 시도하게 되면 , 당연히 예외가 발생하는것이다.

cr0에 값을 쓰기전에 인터럽트를 해제시켜주는 이유는 ,   인터럽트 서비스 루틴에 의해서 CR0값이 변경될 가능성이 있기 때문이다.

보통 인터럽트의 IRQL은  일반 커널 쓰레드의 PASSIVE_LEVEL보다 높은 값을 지니기때문에 , 언제든지 CPU를 선점할수 있게된다.

저작자 표시 비영리 변경 금지
신고
by Sone 2009.08.22 16:17
| 1 |