[ kernel ] 루트킷 분석하다가 조사한 커널 함수들.
Init_module : 커널함수의 시작은 main 대신 init_moudle를 사용함.
IOCTL : read(), write() 와같이 읽기 쓰기 처리가 가능 -> 하드웨어의 제어나 상태를 얻기 위해 사용
Inet_add_protocol : 새로운 네트워크 프로토콜을 설정할수있음
Inet_del_protocol : 기존 네트워크 프로토콜 삭제
create_proc_entry : proc 파일 시스템에서 접근 할 수 있는 파일을 만든다. 만들 수 있는 최상위 디렉토리는 /proc 이다. (구조체로 존재)
i_node 구조 (리눅스 디폴트 파일 시스템 ex2, ex3 가 채택)
- i-mode : 파일의 속성 및 접근제어 정보 ( 정규파일 : S_IFREG , 디렉터리 : S_IFDIR , 장치파일 : S_IFCHR , 블록장치파일 : S_IFBLK , 파이프 : S_IFFIFO, 소켓 : S_IFSOCK
MODULE_PARM(char * modname, "s") // kernel 2.4 부터 insmod 시 인자를 받을 수 있도록 구성되었는데, s 는 문자열 형태를 받겠다는 뜻
int gettimeofday(struct timeval *tv, struct timezone *tz); : timezone 을 설정함
copy_from_user(void * to, const void __user * from, unsigned long n) : 사용자 메모리 블록 데이터를 커널 메모리 블록 데이터에 써 넣는다.
(from 사용자메모리, to 커널메모리)
nl->next = kmalloc(sizeof(struct nethide_list), GFP_KERNEL);
GFP_ATOMIC | 메모리가 있으면 할당 없으면 NULL. 휴면 불가능 |
GFP_KERNEL | 메모리 할당이 항상 성공하도록 요구, 메모리가 충분하지 않을 경우는 호출한 프로세스를 멈추고 동적 메모리 할당할 수 있는 상태가 될 때까지 대기. 휴면가능. |
GFP_USER | 유저 메모리를 할당함. 휴면 가능 |
GFP_DMA | 연속된 물리 메모리를 할당 받을 때 사용 |
즉, /dev/mem은 실제 물리 메모리, /dev/kmem은 커널 가상 메모리 공간에 접근할 수 있는 디바이스 파일입니다.
- A Hook, 우선순위1, B Hook, 우선순위2, C Hook, 우선순위3 이 있을 때 nf_register_hook( D Hook, 우선순위2 ) 하면 아래처럼 됨
- A Hook, 우선순위1, B Hook, 우선순위2 , D Hook, 우선순위2 ,C Hook, 우선순위3
EXPORT_NO_SYMBOLS : 전역 변수와 전역 함수를 커널 심볼 테이블에 등록해 놓음 ( 공개되지 않은 코드임 )
Dentry 란 ? : 해당 디렉토리가 포함하고 있는 디렉토리와 파일정보를 보유 하고 있음
Getdents() Get directory entrys : 디렉토리의 속성을 가져옴
query_module() : 함수를 이용해 커널 심볼 테이블과 커널에 적재된 다른 모듈의 심볼 테이블을 구한다. 이때 query_module() 함수에 QM_MODULES, QM_INFO, QM_SYMBOL 값을 지정하여 필요한 정보를 가져오는데, QM_MODULES는 커널에 포함된 모듈명을 얻어올 때 사용하며, QM_INFO는 각 모듈의 시작 주소와 크기를 얻기 위해 사용한다. 앞에서 구한 모듈 정보를 통해 QM_SYMBOL로 실질적인 커널 심볼 테이블과 커널에 적재된 다른 모듈의 심볼 테이블을 구한다
___this_module : 현재 커널을 가리키고 있는 커널 내부 변수 명
Ex)struct module *m = &__this_module;
Sysenter : sysenter가 호출되면 IA32_SYSENTER_EIP를 참고하여 KiFastCallEntry가 호출되는 것을 알 수 있었다.
커널 2.6 부터는 시스템 테이블을 그냥 오버라이딩 할 수 없기 때문에 나온 것.
SSDT 후킹은 윈도우즈 API 가 커널 모드에서 서비스를 받기 위해 필요한 SSDT(System Service Descriptor Table) 의 내용을 조작하는 커널모드 후킹 방법 중에 하나 이다.
sysenter 명령은 유저모드에서 사용되는 명령어로, 현재 스레드가 유저모드에서 커널모드로 진입 시켜주는 역할을 한다. 인텔 메뉴얼에 보면 SYSENTER_EIP_MSR 가 가르키는 위치를 eip 레지스터에 넣어 실행 한다고 나와 있는데, 이 값은 MSRs(MODEL-SPECIFIC REGISTERS) 의 0x176 주소에서 가져온다. MSRs 는 rdmsr 명령으로 읽어올 수 있다.
IDT ( Interrupt Descriptor Table ) : 프로세서에서 인터럽트 혹은 exception 이 걸렸을 경우에 수행해야할 핸들러의 주소를 저장해 놓은것을 인터럽트 혹은 excetpion vector 라고 한다. 인텔 프로세서에서는 이러한 인터럽트 혹은 eception 핸들러들의 벡터와 벡터의 정보등을 저장해두는 구조체를 IDT 라고 부른다.
IDTR : 펜티엄에는 IDTR 이라 불리우는 특별한 레지스터가 존재한다. 이 레지스터는 시스템의 IDT가 존재하는 메모리 주소의베이스 어드레스와
IDT entry 의 개수가 저장되기로 약속된 레지스터 이다.
CPU 코어마다 IDTR과 해당 IDTR이 가리키는 IDT table 이 그 개수만큼 존재한다.
예를 들어 듀얼코어라면 IDTR은 2개가 되고 IDT Table 은 두개가 된다. 그래서 보통 CPU 개수를 구해서 모든 IDT를 조작하는 방식을 사용한다.
__asm sidt var : 해당 명령어를통해 var 변수에 IDT Entry[0] 번째 값이 들어간다.
__asm cli : 인텁트 발생 불가상태
__asm sti : 인터럽트 발생 가능 상태
rwlock_init : thread lock 을 읽고 쓸 수 있음
Kernel_thread : 예전에 2.4.* 커널에서는 kernel_thread 함수을 직접 이용해서 thread 를 생성하고 스레드를 종료시킬때 complete을 이용해서 스레드 함수가 완전해 종료될때 까지 기다렸다가 모듈을 종료하였는데 2.6 의 현재 최신커널에서는 kthread을 사용하여 해서 위의 작업을 하는 함수가 만들어져 있다.
proc_dir_entry : 프로세스 디렉토리 속성값을 가지고 있는 커널 구조체
User_path_walk : it get the filename passed as argument and retrive the inode informations.. :)
lookup_dentry() : 파일 경로명을 가져온다. 그리고 엔트리 값을 반환한다.
GFP_KERNEL option으로 호출하면, kmalloc이 당장은 메모리가 모잘라도 메모리가 생길 때까지 계속 try하는 반면에...
GFP_USER option으로 호출하면, 메모리 부족하면 대충 fail로 끝나버리는 차이를 말하는 듯합니다.
inet_add_protocol() : 프로토콜 모듈 추가
nf_register_hook() 함수 : netfilter 후킹할때 사용하는데. 정확한 사전적 용어는 못찾음
init_mm은 mm_struct 라는 구조체로 이루어져 있는데 다음과 같다.
위의 mm_struct 의 주석내용을 보면 다음과 같습니다.
"owner"는 지금 mm struct의 user/owner인 정규(canonical) task를 가르켜야 한다.
init_task는 다음과 같다.
따라서 만약에 owner 가 바뀌기 위해서는 다음과 같은 과정이 행해져야 한다.
현재 task == mm->owner
현재 task의 mm != mm
새로운 task->mm = mm
새로운 task->alloc_lock 이 잠겨있어야 owner가 바뀔 수 있다.
'C,C++ > C' 카테고리의 다른 글
[ attribute 관련 속성 정리 ] (0) | 2014.07.02 |
---|---|
LINUX dlopen 으로 dynamic 하게 library 호출 (0) | 2014.04.24 |