- 论坛徽章:
- 0
|
--[ 7.2 rkchecker.c(usermode app)
- /*
- * Name: rkchecker.c
- * Author: CoolQ
- * License: GPL
- * Intro: try to find some kernel rootkits
- * Usage: # insmod dump.ko
- * # cat kernel.info
- * .text = 0xc0100000
- * idtr = 0xaaaaaaaa
- * sys_call_off = 0xbbbbbbbb
- * sys_call_table = 0xcccccccc
- * sys_call_nr = dd
- * # ./rkchecker -m ./kernel.dat -d /boot/vmlinuz -s 0xcccccccc -n dd
- * if you use 4G/4G patch, use
- * # ./rkchecker -4 -m ./kernel.dat -d /boot/vmlinuz -s 0xcccccccc -n dd
- */
- #include <stdio.h>
- #include <stdlib.h>
- #include <unistd.h>
- #include <fcntl.h>
- #include <string.h>
- #include <getopt.h>
- #include <sys/mman.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #define KERNEL_DISC_FILE "/boot/vmlinuz"
- #define KERNEL_TMP_GZ_FILE "/tmp/kernel.gz"
- #define KERNEL_TMP_FILE "/tmp/kernel"
- #define KERNEL_DUMP_FILE "./kernel.dat"
- #define MAGIC_GZ 0x00088b1f
- #define TEXT_START 0xc0100000
- #define TEXT_START_4G 0x02100000
- #define THRESHOLD 100
- #define SYS_CALL_NR 240
- #define ERROR(str) \
- do{ \
- perror(str); \
- return -1; \
- }while(0)
- int extract_file(const char *file);
- unsigned int find_text_end(const char *file);
- int check(const char *file_mem, const char *file_store, unsigned int offset);
- int check_text(void *start_mem, void *start_store, unsigned int len);
- int check_exceptiontbl(void *start_mem, void *start_store);
- int check_syscalltbl(void *start_mem, unsigned int sys_call_off,
- unsigned int nr);
- void usage(const char *prog);
- static char *g_krnl_mem = KERNEL_DUMP_FILE;
- static char *g_krnl_store = KERNEL_DISC_FILE;
- static int g_threshold = THRESHOLD;
- static unsigned int g_text_start = TEXT_START;
- static unsigned int g_sys_call_off;
- static unsigned int g_sys_call_nr = SYS_CALL_NR;
- static unsigned int g_text_end_off;
- int main(int argc, char *argv[])
- {
- int ret;
- char *tmp;
- if(argc < 4)
- usage(argv[0]);
-
- while((ret = getopt(argc, argv, "m:d:t:s:n:4")) != -1){
- switch(ret){
- case 'm':
- g_krnl_mem = strdup(optarg);
- break;
- case 'd':
- g_krnl_store = strdup(optarg);
- break;
- case 't':
- g_threshold = atoi(optarg);
- break;
- case 's':
- g_sys_call_off = strtoul(optarg, &tmp, 16) - g_text_start;
- break;
- case '4':
- g_text_start = TEXT_START_4G;
- break;
- case 'n':
- g_sys_call_nr = atoi(optarg);
- break;
- default:
- usage(argv[0]);
- break;
- }
- };
-
- ret = extract_file(g_krnl_store);
- if(ret == -1)
- exit(EXIT_FAILURE);
-
- unlink(KERNEL_TMP_FILE);
- ret = system("gzip -d " KERNEL_TMP_GZ_FILE);
- if(ret == -1)
- ERROR("ungzip error.\n");
- g_text_end_off = find_text_end(KERNEL_TMP_FILE);
- printf("[i] .text end at 0x%x\n", g_text_end_off);
- ret = check(KERNEL_TMP_FILE, g_krnl_mem, g_text_end_off);
- if(ret == -1){
- fprintf(stdout, "! your kernel maybe hacked.\n");
- return -1;
- }
-
- unlink(KERNEL_TMP_FILE);
- return 0;
- }
- int extract_file(const char *file)
- {
- struct stat st;
- int fd_read, fd_write;
- int mag = MAGIC_GZ;
- int len_gz;
- char *addr_read, *addr_write, *addr_gz;
- if(stat(file, &st) == -1)
- ERROR("stat error.\n");
-
- fd_read = open(file, O_RDONLY);
- fd_write = open(KERNEL_TMP_GZ_FILE, O_RDWR | O_TRUNC | O_CREAT,
- S_IRWXU | S_IRGRP | S_IROTH);
- if(fd_read == -1 || fd_write == -1)
- ERROR("open error.\n");
- addr_read = mmap(0, st.st_size, PROT_READ, MAP_SHARED, fd_read, 0);
- if(addr_read == MAP_FAILED)
- ERROR("map failed.\n");
-
- addr_gz = memmem(addr_read, st.st_size, &mag, 4);
- if(addr_gz == NULL)
- ERROR("not a bzImage\n");
- len_gz = st.st_size - (int)(addr_gz - addr_read);
-
- if(lseek(fd_write, (off_t)(len_gz - 1), SEEK_SET) == (off_t)-1)
- ERROR("lseek error.\n");
- write(fd_write, "a", 1);
-
- addr_write = mmap(0, len_gz, PROT_WRITE, MAP_SHARED, fd_write, 0);
- if(addr_write == MAP_FAILED)
- ERROR("map failed.\n");
- memcpy(addr_write, addr_gz, len_gz);
-
- munmap(addr_read, st.st_size);
- munmap(addr_write, len_gz);
- close(fd_read);
- close(fd_write);
-
- return 0;
- }
- unsigned int find_text_end(const char *file)
- {
- int fd, count;
- struct stat st;
- void *addr;
- unsigned int *p, *tmp;
-
- stat(file, &st);
-
- fd = open(file, O_RDONLY);
- if(fd == -1)
- ERROR("open error.\n");
-
- addr = mmap(0, st.st_size, PROT_READ, MAP_SHARED, fd, 0);
- if(addr == MAP_FAILED)
- ERROR("map error.\n");
- p = addr;
- while((char *)p - (char *)addr < st.st_size){
- if((*p >> 24) == (g_text_start >> 24)){
- tmp = p;
- for(count = 0; count < g_threshold; count++, p++)
- if((*p >> 24) != (g_text_start >> 24) &&
- !((*p >> 16) == 0xffff &&
- (g_text_start >> 24)==(TEXT_START_4G >>24)
- )
- )
- break;
- }else
- p++;
- if(count == g_threshold){
- munmap(addr, st.st_size);
- close(fd);
- return((char *)tmp - (char *)addr);
- }
- }
- munmap(addr, st.st_size);
- close(fd);
- return 0;
- }
- int check(const char *file_mem, const char *file_store, unsigned int offset)
- {
- int ret, ret2, ret3;
- int fd_mem, fd_store;
- void *addr_mem, *addr_store;
- struct stat st_mem, st_store;
- ret = 0;
-
- ret = stat(file_mem, &st_mem);
- ret |= stat(file_store, &st_store);
- if(ret)
- ERROR("stat error.\n");
-
- fd_mem = open(file_mem, O_RDONLY);
- fd_store = open(file_store, O_RDONLY);
- if(fd_mem == -1 || fd_store == -1)
- ERROR("open file error.\n");
- addr_mem = mmap(0, st_mem.st_size, PROT_READ, MAP_SHARED, fd_mem, 0);
- addr_store = mmap(0, st_store.st_size, PROT_READ, MAP_SHARED,
- fd_store, 0);
- if(addr_mem == MAP_FAILED || addr_store == MAP_FAILED)
- ERROR("mmap error.\n");
- ret = check_text(addr_mem, addr_store, offset);
- if(!ret)
- fprintf(stdout, " - .text check passed.\n");
- ret2 = check_exceptiontbl(addr_mem + offset, addr_store + offset);
- if(!ret2)
- fprintf(stdout, " - exception table check passed.\n");
- ret3 = check_syscalltbl(addr_mem, g_sys_call_off, g_sys_call_nr);
- if(!ret3)
- fprintf(stdout, " - sys_call_table check passed.\n");
-
- munmap(addr_mem, st_mem.st_size);
- munmap(addr_store, st_store.st_size);
- close(fd_mem);
- close(fd_store);
-
- return(ret | ret2 | ret3);
- }
- int check_text(void *start_mem, void *start_store, unsigned int len)
- {
- unsigned char *p_mem, *p_store;
- int count, ret;
-
- fprintf(stdout, "[+] Start checking .text section.\n");
- ret = 0;
-
- for( p_mem = start_mem, p_store = start_store, count = 0;
- count < 10000 && ((char *)p_mem - (char *)start_mem) < len;
- p_mem++, p_store++
- )
- if(*p_mem != *p_store){
- if(*p_mem == 0xf0 && *p_store == 0x0f){
- if( *(p_mem + 1) == 0x83 &&
- *(p_store + 1) == 0xae &&
- *(p_mem + 2) == 0x44 &&
- (*(p_store + 2) == 0xe8 ||
- *(p_store + 2) == 0xf0) &&
- *(p_mem + 3) == 0x24 &&
- *(p_store + 3) == 0x8d &&
- *(p_mem + 4) == 0x00 &&
- *(p_store + 4) == 0x76
- ){
- p_mem += 5;
- p_store += 5;
- continue;
- }
- }else if(*p_mem == 0x8d && *p_store == 0x0f){
- if( (*(p_mem + 1) == 0x74 &&
- *(p_store + 1) == 0x18 &&
- *(p_mem + 2) == 0x26 &&
- /* *(p_store + 2) == 0x01 && */
- *(p_mem + 3) == 0x00 /* &&
- *(p_store + 3) == 0x90*/) ||
- (*(p_mem + 1) == 0x44 &&
- /* *(p_store + 1) == 0x18 && */
- *(p_mem + 2) == 0x20 &&
- /* *(p_store + 2) == 0x08 && */
- *(p_mem + 3) == 0x00 &&
- *(p_store + 3) == 0x90)
- ){
- p_mem += 4;
- p_store += 4;
- continue;
- }
- }else if(*p_mem == 0x66 /*&& *p_store == 0x0f*/){
- if( (*(p_mem + 1) == 0x66 &&
- /**(p_store + 1) == 0x18 &&*/
- *(p_mem + 2) == 0x66 &&
- /**(p_store + 2) == 0x01 &&*/
- *(p_mem + 3) == 0x90 /* &&
- *(p_store + 3) == 0x90)*/ )
- ){
- p_mem += 4;
- p_store += 4;
- continue;
- }
- }
- ret = -1;
- count++;
- fprintf(stdout, "mismatch no. %d at offset 0x%x",
- count, (char *)p_mem - (char *)start_mem);
- fprintf(stdout, "\tstore = %02X, mem=%02X\n",
- *p_mem, *p_store);
- }
-
- return ret;
- }
- int check_exceptiontbl(void *start_mem, void *start_store)
- {
- unsigned int *p_mem, *p_store;
- int ret;
-
-
- ret = 0;
- fprintf(stdout, "[+] Start checking exception table.\n");
- if(((int)start_mem & 0x0000000f) != 0x0)
- fprintf(stdout, " - the offset is weird, not aligned.\n");
-
- for( p_mem = start_mem, p_store = start_mem;
- ((*p_store >> 24) == (g_text_start >> 24) ||
- ((*p_store >> 16) == 0xffff &&
- (g_text_start == TEXT_START_4G)
- ));
- p_mem++, p_store++
- )
- if(*p_mem != *p_store){
- fprintf(stdout, " - suspect except handler at 0x%x",
- (unsigned int)p_mem);
- ret = -1;
- }
-
- if(((int)p_store & 0x0000000f) != 0x0)
- if(*p_store != 0){
- fprintf(stdout, " - seems weired at 0x%x, "
- "kernel file unreliable.\n", p_store);
- ret = -1;
- }
- fprintf(stdout, " [i] exception tabled end at __ex_table + 0x%x\n",
- (unsigned int)((char *)p_mem - (char *)start_mem));
- return ret;
- }
- int check_syscalltbl(void *start_mem, unsigned int sys_call_off,
- unsigned int nr)
- {
- unsigned int *p;
- int i, ret;
-
- fprintf(stdout, "[+] Start checking sys_call_table.\n");
- fprintf(stdout, " [i] checknig %d items.\n", nr);
-
- ret = 0;
- p = (int *)((char *)start_mem + sys_call_off);
-
- for(i = 0; i < nr; i++, p++)
- if(*p < g_text_start || *p > g_text_start + g_text_end_off){
- fprintf(stdout, " - sys_call no. %d suspicious."
- "point to value %x\n", i, *p);
- ret = -1;
- }
-
- return ret;
- }
- void usage(const char *prog)
- {
- fprintf(stderr, "Usage: %s [-4] [-t num] [-n num] -m file_1 -d file_2"
- "-s addr\n",
- prog);
- fprintf(stderr, "Params:\n");
- fprintf(stderr, " -4: The kernel uses 4G/4G patch.\n");
- fprintf(stderr, " -t num: Set threshold to num.\n");
- fprintf(stderr, " -n num: Set sys_call_numbers to num.\n");
- fprintf(stderr, " -m file: Set memory dump file to file_1\n");
- fprintf(stderr, " -d file: Set disc kernel file to file_2\n");
- fprintf(stderr, " -s addr: Set the sys_call_table to addr\n");
- exit(EXIT_FAILURE);
- return;
- }
复制代码 |
|