본문 바로가기

Programming

x86 linux idt hooking

리눅스에서 LKM 을 올려서 IDT 를 후킹하는 실습을 했다


먼저 SIDT 명령으로 IDTR 레지스터의 6바이트 내용을 메모리로 가져온다

하위 4바이트에 IDT 의 가상주소가 들어있다.


테스트 환경(VBox Ubuntu 2.6) 에서는 0xc0763000 이었다.


간단하게 IDT 의 첫번째 엔트리(divide by zero exception) 을 후킹해보기 위해서

IDT 엔트리의 주소를 덮어썻다.

IDT 엔트리는 8바이트로 이루어져 있는데 다음과 같은 구조다


// Took these structures from Bran's Kernel Dev Tutorial
008typedef struct _idt_entry
009{
010    USHORT base_lo;
011    USHORT sel;
012    UCHAR always0;
013    UCHAR flags;
014    USHORT base_hi;
015} idt_entry, *pidt_entry;
016 
017typedef struct _idt_ptr
018{
019    USHORT limit;
020    ULONG base;
021} idt_ptr, *pidt_ptr;


덤프를 떳을대 모양은 아래와 같다.


00604050 C0108E00 

0060C130 C0588E00 

0060C190 C0588E00 

0060C2C0 C058EE00

...


첫번째 엔트리인 00604050 C0108E00 에서 base_lo 의 부분이 

4050 인데, 이것이 핸들러 주소의 하위 2바이트이고

base_hi 부분이 C010 인데 이것이 핸들러 주소의 상위 2바이트이다.

이 부분들을 내가 지정한 함수의 주소로 수정하는 코드를 아래와 같이

LKM 으로 만들어서 컴파일했다.



#include "linux/init.h"
#include "linux/kernel.h"
#include "linux/module.h"
#include "linux/proc_fs.h"
#include "linux/syscalls.h"
#include "linux/kallsyms.h"
#include "linux/sched.h"
#include "asm/uaccess.h"
#include "asm/unistd.h"

unsigned char* p_idt = (unsigned char*)0xc0763000;

void my_idt_hook(){
	printk("idt 0 hooked\n");
}

int my_init(void)
{

//	printk("module init ok\n");
//	asm("sidt %0\n" : :"m"(p_idt[25]));

	printk("gogogo\n");

	write_cr0( read_cr0( ) & ( ~0x10000 ) );

/*	int i;
	for(i=0; i<256; i++){
		printk("%08X ", p_idt[i]);
	}
*/

	p_idt[0] = (unsigned int)my_idt_hook & 0xFF;
	p_idt[1] = ((unsigned int)my_idt_hook & 0xFF00) >> 8;

	p_idt[6] = ((unsigned int)my_idt_hook & 0xFF0000) >> 16;
	p_idt[7] = ((unsigned int)my_idt_hook & 0xFF000000) >> 24;

	write_cr0( read_cr0( ) | 0x10000 );

	printk("ok?\n");

/*
	int k=1;
	for(i=0; i<8*20; i++){
		printk("%02X ", p_idt[i]);
		if(k++ % 8 == 0) printk("\n");
	}
*/	return 0;
}

void my_exit(void)
{
	printk("module unloaded\n ");
}
module_init(my_init);
module_exit(my_exit);


그리고 divide by zero exception 을 일으키는 프로그램을 만들어서 실행시키고

dmesg 를 해보니 아래와같이 내가 정의한 my_idt_hook 함수가 호출된 것을 확인 할 수 있었다.

후킹한 ISR 함수를 제대로 안만들어서 kernel panic 이 되었지만 요점은 후킹이 성공했다는 점이다.





'Programming' 카테고리의 다른 글

QEMU Detection  (0) 2013.01.28
Anti Debugging with POP SS  (0) 2013.01.28
gcc inline assembly  (0) 2013.01.24
x86 Segment Registers  (1) 2013.01.24
x86 address/operand 16/32 bit setting  (0) 2013.01.23