메모장 입니다2
IDT 후킹 본문
1.인터럽트(Interrupt)
-CPU 작업 중, 다른 장치나 예외상황의 일처리가 필요할 경우, 프로세서에게 알리는 것.
(<->폴링: 어떤 장치의 처리를 위해, 주기적으로 감시하는 것)
2.IDT(Interrupt Descriptor Table)
-정의
->인터럽트 서비스 루틴이 담긴 배열.
->(*보호모드일 때) 8바이트의 256개의 엔트리로 구성됨.
->-각 엔트리는 ISR의 주소와 보안 관련 정보가 담김.
-IDT Enty 구성
#pragma pack(1)
typedef struct
{
unsigned short LowOffset;
unsigned short selector;
unsigned char zero;
unsigned char type_attr;
unsigned short HiOffset;
} IDTENTRY;
#pragma pack()
->Low/Hi Offset은 ISR의 주소를 나타낸다.
->IDTENTRY 구조체 멤버는 프로세서에 따라 다르다.
-인터럽트 서비스 루틴(ISR)
->해당 인터럽트 발생시, 실행될 코드가 담긴 루틴.
->인터럽트 벡터라고도 함.
-인터럽트 오브젝트
->인터럽트와 관련된 주요정보가 담김.
>>ServiceRoutine 주소, 인터럽트 레벨 정보 등.
->ISR 내부에서 호출되는 nt!KiInterruptDispatch()의 인자로 전달되어,
인터럽트 권한이 설정된 뒤, ServiceRoutine이 실행됨.
*ISR: 인터럽트 설정 과정(트랩프레임 구성, IRQL 조정, 시스템 인터럽트 Enable)을 진행한 후에
InterruptDispatch() 호출.
->InterruptDispatch()내부에서 ServiceRoutine이 호출됨.
*ServiceRoutine: 실질적인 인터럽트 처리 코드가 담긴 루틴.
-IDT 구하기
`IDTR을 이용`
->IDTR 레지스터에 IDT의 주소가 담김.
->IDTR은 명령어를 통해 값을 조작할 수 있다.
1)SIDT(Store IDT)
->IDTR의 값을 다음 구조체 형태로 반환.
typedef struct
{
unsigned short IDTLimit;
unsigned short LowIDTbase;
unsgined short HiIDTbase;
}IDTINFO;
->High, Low가 나뉘어 있기 때문에, 매크로(MAKELONG)을 통해 4바이트로 합쳐줘야 한다.
#define MAKELONG(low, high) ((unsigned long) (((unsigned short) (low)) I ((unsigned long) ((unsigned short) (high))) << 16))
2)LIDT(Load IDT)
->IDTR의 값을 변경. //예제에서 사용되진 않음. IDT가 아니라 IDT 멤버를 조작하는 것이기 때문.
`PCR(Processor Control Region)을 이용`
-Interrupt Object 구하기
->운영체제 버전에 따라 다름
1)XP
: ISR 시작주소 - 0x3c.
2)7
:아직 확인안됨(0x3c 빼는 것으론 구할 수 없음.)
->InterruptDispatch의 인자로 전달되는 값을 확인하여 알 수 있다.
->Windows 10에선 오브젝트의 위치가 고정되지 않기 때문에, 이 방식으로 찾을 수 없다.
http://m.blog.naver.com/gloryo/220400046050
-IDT Hooking 탐지
->명확한 기준이 없다.
인터럽트의 처리루틴은 불특정 영역에 존재하기 때문에.
(<-> SSDT 후킹 탐지: ntoskernel.exe 영역에만 존재.)
->추측을 통한 방지만
/*키보드 인터럽트 루틴(ServiceRoutine)을 후킹하여 PS/2 스캔코드 출력*/
/*소스*/
#include <ntddk.h>
#include <stdio.h>
#define MAKELONG(low, high) (unsigned long) (((unsigned short) low) | ((unsigned long) (((unsigned short) high) << 16)))
#define MAX_IDT_ENTRY 150
#define Vector_Keyboard_XP 0x93
#define Vector_Keyboard_10 0x70
#pragma warning(disable: 4214)
#pragma warning(disable: 4013)
#pragma warning(disable: 4047)
#pragma warning(disable: 4024)
#pragma warning(disable: 4616)
#pragma warning(disable: 4101)
#pragma warning(disable: 4305)
#pragma warning(disable: 4333)
#pragma pack(1)
typedef struct
{
unsigned short LowOffset;
unsigned short selector;
unsigned char zero;
unsigned char type_attr;
unsigned short HiOffset;
} IDTENTRY;
#pragma pack()
typedef struct
{
unsigned short IDTLimit;
unsigned short LowIDTbase;
unsigned short HiIDTbase;
}IDTINFO;
typedef struct _KINTERRUPT {
CSHORT Type;
CSHORT Size;
LIST_ENTRY InterruptListEntry;
ULONG ServiceRoutine;
PVOID ServiceContext;
KSPIN_LOCK SpinLock;
ULONG TickCount;
PKSPIN_LOCK ActualLock;
PLONG DispatchAddress;
ULONG Vector;
KIRQL Irql;
KIRQL SynchronizeIrql;
UCHAR FloatingSave;
UCHAR Connected;
CHAR Number;
UCHAR ShareVector[3];
KINTERRUPT_MODE Mode;
ULONG ServiceCount;
ULONG DispatchCount;
ULONG DispatchCode[106];
} KINTERRUPT, *PKINTERRUPT;
VOID WP_OFF()
{
__asm {
push eax
mov eax, CR0
and eax, 0x0FFFEFFFF
mov CR0, eax
pop eax
}
}
VOID WP_ON()
{
__asm {
push eax
mov eax, CR0
or eax, NOT 0x0FFFEFFFF
mov CR0, eax
pop eax
}
}
//////////////
ULONG OldServiceRoutine;
PKINTERRUPT IntObject;
/////////////
__declspec(naked) MyServceRoutine()
{
unsigned char c;
DbgPrintEx(DPFLTR_IHVDRIVER_ID, 0, "MyServiceRoutine!!\n");
c=READ_PORT_UCHAR(0x60);
WRITE_PORT_UCHAR(0x64, c);
DbgPrintEx(DPFLTR_IHVDRIVER_ID, 0, "scan code: %x\n", c);
__asm {
jmp [OldServiceRoutine]
}
}
VOID OnUnload(PDRIVER_OBJECT DriverObject)
{
UNREFERENCED_PARAMETER(DriverObject);
IntObject->ServiceRoutine = OldServiceRoutine;
DbgPrint("Unloading Dirver!!!");
}
NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
{
IDTINFO idt_info;
IDTENTRY* idt_entries;
IDTENTRY* keyEntry;
int count;
UNREFERENCED_PARAMETER(RegistryPath);
DbgPrint("Driver Loading!!");
DriverObject->DriverUnload = OnUnload;
//////////////
/* IDT 테이블의 각 ISR 주소값 DbgPrint*/
/*IDT 주소 가져오기*/
__asm sidt idt_info
idt_entries = (IDTENTRY*)(((unsigned int)idt_info.HiIDTbase << 16U) | (idt_info.LowIDTbase));
DbgPrintEx(DPFLTR_IHVDRIVER_ID, 0, "IDT:%4x\n", idt_entries);
keyEntry = (IDTENTRY*)(((unsigned int)idt_entries[Vector_Keyboard_XP].HiOffset << 16U) | (idt_entries[Vector_Keyboard_XP].LowOffset));
DbgPrintEx(DPFLTR_IHVDRIVER_ID, 0, "KEY IDT:%4x\n", keyEntry);
/*보호모드 테스트 w10
WP_OFF();
keyEntry->HiOffset = ((unsigned short) MyServceRoutine >> 16);
keyEntry->LowOffset = ((unsigned short)MyServceRoutine);
WP_ON();
*/
IntObject = (PKINTERRUPT)((ULONG)keyEntry - (ULONG)0x3c);
OldServiceRoutine= IntObject->ServiceRoutine;
IntObject->ServiceRoutine = MyServceRoutine;
DbgPrintEx(DPFLTR_IHVDRIVER_ID, 0, "KEY ServiceRoutine:%4x\n", OldServiceRoutine);
/*idt entry 출력
for (count = 0; count < MAX_IDT_ENTRY; count++)
{
char _t[255];
char _t2[255];
IDTENTRY *i = &idt_entries[count];
unsigned long addr = 0;
addr = ((unsigned int)i->HiOffset << 16U) | (i->LowOffset);
_snprintf(_t2,
253,
"[%d] idt_entry:%x\n", count, (unsigned int)i);
DbgPrintEx(DPFLTR_IHVDRIVER_ID, 0, _t2);
_snprintf(_t,
253,
"Interrupt %d: ISR %4x\n", count, addr);
DbgPrintEx(DPFLTR_IHVDRIVER_ID, 0, _t);
}*/
return STATUS_SUCCESS;
}
'Study > Programming' 카테고리의 다른 글
Windows] SSDT 후킹 - 탐지 (0) | 2017.08.08 |
---|---|
Windows] SSDT 후킹 - ZwQuerySystemInformation Hook Source (0) | 2017.08.08 |
Windows] SSDT 후킹 - 설명 (0) | 2017.03.17 |
Windows] SSDT 후킹 - MDL 활용. (0) | 2017.03.16 |
Windows] 드라이버 개발 - 6) IRP (0) | 2017.02.24 |