2014.05.02 16:58

[ 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은 커널 가상 메모리 공간에 접근할 수 있는 디바이스 파일입니다.

 

  • Hook, 우선순위1B Hook, 우선순위2C Hook, 우선순위 있을  nf_register_hook( D Hook, 우선순위2 ) 하면 아래처럼 
  • Hook, 우선순위1B Hook, 우선순위2 , D Hook, 우선순위,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

위의 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가 바뀔 수 있다.


Posted by k1rha