시스템 콜 후킹은 해킹 위험 때문에 맨날 막히는데 구글로 찾아보고 하니 뚫린다.
사실 뚫었다고 하긴 뭐하지만..
Exploiting races in system call wrappers
http://lwn.net/Articles/245630/
뭐 대충 시스템 콜 상속에 관한 논문.
http://www.seclab.cs.sunysb.edu/anupama/papers/syscall_inherit.pdf
원래 참고한 블로그 글 (감사합니다!)
http://blog.naver.com/PostView.nhn?blogId=passket&logNo=100111928670
하이재킹의 방법은 여러가지가 있는데 보통 sys_call_table 내용을 엎어치기 하는 트릭이다. 최근 커널에는 cr0 트릭이 먹힌다.
http://www.troot.co.kr/tc/2644
뭐 커널 소스 직접 건든다면 바로 익스포트
http://blog.naver.com/parkys1982?Redirect=Log&logNo=30003953701
이렇게 테이블 위치를 찾을 수도 있다.
http://teamcrak.tistory.com/50
비슷한 글
http://www.mareq.com/2008/05/linux-unix-system-calls-wrapping.html
이건 libc 레벨에서의 꼼수. 그러니까 libc를 preload 하고 심볼 찾아서 내 함수로 대치하면 libc에서 커널 쪽으로 안 보내고 내 함수를 부른다.
http://kldp.org/node/83447
물론 시스템 병신 만들기 싫으면 내 함수 호출 후 원래 함수도 호출해야 함 (래핑)
사실 libc 래핑도 할 수 있음. gcc 기능으로.
http://www.troot.co.kr/tc/2641
해킹하려고 찾아본 건 아니다. 시스템 콜 실험을 할 때 매번 재빌드 하기 귀찮아서 찾아봄.
해킹 기법이 아니라 슈퍼유저 권한을 사용한다. 사용하지 않고도 할 수 있지만 보통 상용 서버라면 중요 툴 실행 권한이 없다.
진짜 해킹을 해서 루트킷을 심고 싶다면.. 피싱 홈페이지나 dns 스푸핑으로 최신 (가짜) 디바이스 드라이버 설치하도록 속이는 방법도 있다. 요즘엔 거의 불가능.
sys_call_table은 정의된 부분은.
arch/x86/kernel/syscall_table_32.S
이걸 딴 데서 가져다 써야하므로, EXPORT 해야 한다. 파일 찾아서 추가.
kernel/i386_ksyms_32.c:EXPORT_SYMBOL(sys_call_table); extern void *sys_call_table; 도 써줘야 한다.
void **가 맞다. 사실 아무렇게나 써도 됨.
하지만 이건 어디까지나 슈퍼유저의 방법이므로 sys_call_table_32.S의 맨 앞 함수를 찾는다.
cat /proc/kallsyms > ddd 한 후 ddd 파일에서 sys_restart를 찾는다. 어라? 사용자 계정으로 보니까 주소가 모두 000 이네?
그렇다면 방법이 또 있다.
grep sys_restart /boot/System... 뒤에 버전은 uname -r 을 하든지 해서 붙임.
여긴 제대로 나옴 ㅋㅋㅋㅋㅋ 이 주소를 직빵 지정하면 됨.
시스템 콜 후킹 하는 커널 모듈을 만들자.
#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>
// 익스포트 안 했다면 알아서 대충 변수명 정해서 아까 얻은 주소 쓰면 됨.
// 위에 링크 글 보면 테이블 주소 찾는 법이 있는데.. 요즘은 또 바뀌었음..;;
// void **syscccc = (void *)c011111......
extern void *sys_call_table[];
// asmlinkage int (*orig_setuid)( uid_t ruid );
// 이 포인터는 뭐 복구용으로 알아서 잘 쓰시고..
asmlinkage int new_syscall(void)
{
printk("dawnsea!!!\n" );
return 0;
}
int __init m_init( void )
{
// orig_setuid = sys_call_table[__NR_dawnsea_1];
write_cr0( read_cr0( ) & ( ~0x10000 ) ); // 이게 중요한 부분
sys_call_table[__NR_dawnsea_1] = new_syscall;
write_cr0( read_cr0( ) | 0x10000 );
printk("Module init, %lx, %lx\n", (unsigned long)sys_call_table, sys_call_table[__NR_dawnsea_1] );
return 0;
}
void __exit m_exit( void )
{
printk( KERN_ALERT "Module exit\n" );
}
module_init( m_init );
module_exit( m_exit );
커널 모듈로 빌드하니까 빨라서 좋다. 모듈로 빌드하자고!
http://www.troot.co.kr/tc/2591
대충 디렉토리 하나 만들고 위에 소스 때려넣고 Makefile을 만들자.
PWD = $(shell pwd)
obj-m += dawnsea3.o
all:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
clean:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
빌드 3초!
아차.. 커널에 빈 시스템 콜을 하나 넣어두자.
http://www.troot.co.kr/tc/2559
빈 시스템 콜에 연결할 함수 본체는. 아래처럼 야메로 짬.
/kernel/dawnsea.c 로 만들고 /kernel Makefile 에 obj-y += dawnsea.o 추가하면 끝.
#include <linux/kernel.h>
#include <linux/sched.h>
#include <asm/types.h>
#include <asm/thread_info.h>
#include <asm/unistd_32.h>
#include <asm/syscalls.h>
#include <asm/cacheflush.h>
asmlinkage int sys_dawnsea_1(void)
{
printk("dawnsea org syscall\n");
return 0;
}
인클루드가 많은 건 이런 저런 실험하다 남은 찌꺼기임.
시스템 콜 넘버 선언 추가하려면 arch/x86/include/asm/unistd_32.h 까보면 됨.
뭐 대충 커널을 빌드하자.
make-kpkg --initrd --append-to-version=dawnseahw1 kernel-image kernel-headers -j 4
arch/x86/include/asm/syscalls.h 에 미리 선언도 해둬야.. 나중에 어플 빌드할 때 asm에서 찾아온다.
...
asmlinkage int sys_dawnsea_1(void);
#endif /* _ASM_X86_SYSCALLS_H */
시스템콜이 호출이 되어야 하니까 어플도 하나 대충 만듬ㅋㅋ
#include <linux/unistd.h>
#include <stdio.h>
main()
// main (int argc, char *argv[])
{
int i;
i = syscall(341); // 아까 추가한 콜 번호.. include.. asm/syscalls.h 하면 NR... 아 귀찮다..
printf("i = %d\n", i);
return 0;
}
insmod dawnsea3.ko 하면 시스템 콜이 바뀐 상태. 즉 sys_dawnsea_1 함수가 new_syscall 로 바뀜
dmesg | tail 로 보면?
[ 71.177668] dawnsea org syscall
[ 80.422611] Module init, c152b220, f8d46020
[ 86.237055] dawnsea!!!
바꼈네?!! 굿!
나중에 cflush 관련 함수랑 set_memory_rw 등등 함수 안짝좀 찾아봅시다.
/arch/x86/mm/pageattr.c 등등에 있음.
setuid 공부도 좀 하자. 왤케 무식하니.