* 요약
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 |
---|