* 요약

https://tssurya.wordpress.com/2014/08/19/adding-a-hello-world-system-call-to-linux-kernel-3-16-0/에 저장된 Adding a Hello World System Call to Linux kernel 3.16.0 내용을 마음대로 해석해서 pwnable.kr 의 sys_upper()를 등록함


* 결론

커널 컴파일시에 주소를 잘 설정해야 한다. 만약 시스템콜주소를 잘못 설정하면 어떠한 일이 발생하느냐? 본인의 경우는 잘못설정해서 꾸웩 하고 시스템이 죽었다.

만약, 컴파일을 다시 한다면 https://memset.wordpress.com/2011/01/20/syscall-hijacking-dynamically-obtain-syscall-table-address-kernel-2-6-x/ 에 나오는 내용을 참조하여

w00t@ubuntu32svr:~$ grep sys_call_table /boot/System.map-$(uname -r) |awk '{print $1}'

c1691100

시스템 콜 테이블 주소를 c1691100으로 다시 컴파일 한다. 으~~~ 2시간을 기다려야 한다. 우선 오늘은 패쑤~~~


계정은 sudo su 명령어로 루트의 권한으로 실행함 아무래도 커널 작업이다 보니 루트로 작업하는 것이 편리함


* 커널 소스 다운로드

https://www.kernel.org/ 여기에서 다운로드. uname -a 해보니 3.16커널 이었음 그래서 아래만 올려져 있는 커널 소스로 다운로드함

 wget  https://cdn.kernel.org/pub/linux/kernel/v3.x/linux-3.16.35.tar.xz


* 커널 소스 압축 해제

압축해제는 /usr/src/ 디렉토리에 함. 다운로드한 폴더에 가서 다음 명령어를 이용하여 압축을 해제함

 sudo tar -xvf linux-3.16.35.tar.xz -C/usr/src/

sudo 는 루트권한으로 실행하라는 명령어. 귀찮으면 sudo su 하고 그냥 작업하면 됨. 다음 작업을 위하여 디렉토리를 이동함

 cd /usr/src/linux-3.16.35 


* 시스템 콜 sys_upper() 정의

커널소스 디렉토에서 upper 디렉토리를 생성하고 디렉토리를 변경함

 mkdir upper ; cd upper


1. "upper.c" 파일을 만든다.

중요한 것이 있다. 각자 환경에 맞도록 SYS_CALL_TABLE의 주소를 수정해야 한다. 만약 수정하지 않으면, 본인의 경우처럼 커널이 사망할 수 있다. 꿱!!!!

root@ubuntu32svr:/usr/src/linux-3.16.35/upper# cat upper.c

// adding a new system call : sys_upper

#include <linux/module.h>

#include <linux/kernel.h>

#include <linux/slab.h>

#include <linux/vmalloc.h>

#include <linux/mm.h>

#include <asm/unistd.h>

#include <asm/page.h>

#include <linux/syscalls.h>


#define SYS_CALL_TABLE 0x8000e348 // manually configure this address!!

#define NR_SYS_UNUSED 223


//Pointers to re-mapped writable pages

unsigned int** sct;


asmlinkage long sys_upper(char *in, char* out){

int len = strlen(in);

int i;

for(i=0; i<len; i++){

if(in[i]>=0x61 && in[i]<=0x7a){

out[i] = in[i] - 0x20;

}

else{

out[i] = in[i];

}

}

return 0;

}

static int __init initmodule(void ){

sct = (unsigned int**)SYS_CALL_TABLE;

sct[NR_SYS_UNUSED] = sys_upper;

printk("sys_upper(number : 223) is added\n");

return 0;

}

static void __exit exitmodule(void ){

return;

}

module_init( initmodule );

module_exit( exitmodule ); 


2. "Makefile"을 만든다.

root@ubuntu32svr:/usr/src/linux-3.16.35/upper# cat Makefile 

obj-y := upper.o


* upper 디렉토리를 커널 Makefile에 추가

변경 전

 core-y          += kernel/ mm/ fs/ ipc/ security/ crypto/ block/ 

변경 후 

 core-y          += kernel/ mm/ fs/ ipc/ security/ crypto/ block/ upper/

여기까지의 과정은 컴파일러에게 upper 디렉토리에 새로운 시스템콜 sys_upper()이 있다는 것을 알려주는 과정이다.


* 새로운 시스템 콜( sys_upper() )을  시스템 콜 테이블(syscall_32.tbl 파일)에 추가

 64비트를 사용하는 경우는 syscall_64.tbl파일을 변경해야 한다.

 cd arch/x86/syscalls

 vi syscall_32.tbl 

223번 라인을 찾아서 변경한다.

 223    i386    upper    sys_upper

223번은 시스템콜의 번호임. 맨 마지막에 추가하는 경우는 맨 마지막 번호에 1을 더해서 사용해야 한다. 이 번호는 나중에 사용자 프로그램에서 사용된다.


* 새로운 시스템 콜( sys_upper() )을 시스템 콜 헤더 파일에 추가

 cd include/linux/

 vi syscalls.h 

맨 아래쪽에 있는 #endof 앞에 다음 라인을 추가한다.

 asmlinkage long sys_upper(char *in, char* out);


* 커널 컴파일에 필요한 주요 파일을 설치

gcc 최신버전, ncurses dev 패키지, 시스템 패키지

 sudo apt-get install libncurses5-dev


* 커널 컴파일

필요한 환경 구성 후 환경파일(.config) 저장

 sudo make menuconfig

만약 기존 컴파일 환경파일 (.config) 이 있는 경우

 sudo make oldconfig 

커널 컴파일

 cd /usr/src/linux-3.16.35 

 make

시스템 환경에 따라서 수시간이 걸림. PC가 좋은 환경이고 virtualbox 에서 컴파일 하는 경우는 본인의 환경에서는 1시간 40분 정도 걸렸다, 일반적으로는 2~3시간 걸린다고 한다.


* 커널 설치 및 업데이트

수정된 커널을 반영하기 위하여 다음의 명령을 실행한다.

 sudo make modules_install install 

커널 설치 명령을 입력하면 모듈이 마구 마구 설치된다. 이것도 수분이 걸린다. 설치 후에 리부팅한다.

 sudo shutdown -r now

 uname -r


* 허거덕 커널 패닉으로 사망

 


* 시스템 콜 테스트

아래 소스를 수정해서 컴파일 후 실행한다.

#include <stdio.h>

#include <linux/kernel.h>

#include <sys/syscall.h>

#include <unistd.h>

int main()

{

         long int amma = syscall(354);

         printf(“System call sys_hello returned %ld\n”, amma);

         return 0;

}

dmesg 명령어로 시스템콜이 호출된 것을 확인한다.

  dmesg

 - 실행결과 -


'module' 카테고리의 다른 글

리눅스 모듈 따로 컴파일 1 - 따라하기  (0) 2016.05.15
Posted by goldpapa
,