Chinaunix首页 | 论坛 | 博客
  • 博客访问: 359142
  • 博文数量: 35
  • 博客积分: 2176
  • 博客等级: 大尉
  • 技术积分: 797
  • 用 户 组: 普通用户
  • 注册时间: 2006-08-13 14:03
文章分类

全部博文(35)

文章存档

2012年(9)

2009年(14)

2008年(12)

我的朋友

分类: BSD

2008-07-23 15:48:59

The following is an algorithmic explanation of find_syscall.c:

1. Check to make sure the user has supplied a syscall name and
number. (No error checking, just checks for two arguments)
2. Setup the array of nlist structures appropriately.
3. Initialize kernel virtual memory access. (kvm_openfiles)
4. Find the address of sysent and the user supplied syscall.
(kvm_nlist)
5. Calculate the location of the syscall in sysent.
6. Copy the syscall's sysent structure from kernel-space to
user-space. (kvm_read)
7. Print out the location of the syscall in the sysent structure
and the location of the executed function.
8. Close the descriptor (kvm_close).

其实我们将是按照这个算法来实现代码:
简单来更改下算法实现,
1. 取到mkdir 系统调用在内存中的地址。
2. 保存sizeof(kmalloc)字节大小的mkdir
3. 把mkdir覆盖写为kmalloc
4. 调用mkdir
5. 恢复mkdir
好了,看看是怎么实现的吧
find_syscall.c
插入代码太烂了点,还是不好使,总是要插在最后。郁闷了一下。。。

/*
 * Takes two arguments: the name of a syscall and corresponding number,
 * and reports the location in memory where the syscall is located.
 *
 * If you enter the name of a syscall with an incorrect syscall number,
 * the output will be fubar. Too lazy to implement a check
 *
 * Based off of Stephanie Wehner's checkcall.c,v 1.1.1.1
 *
 * find_syscall.c,v 1.0 2005/05/20
 */



#include <stdio.h>
#include <fcntl.h>
#include <kvm.h>
#include <nlist.h>
#include <limits.h>
#include <sys/types.h>
#include <sys/sysent.h>
#include <sys/syscall.h>

int main(int argc, char *argv[]) {

    char errbuf[_POSIX2_LINE_MAX];
    kvm_t *kd;
    u_int32_t addr;
    int callnum;
    struct sysent call;
    struct nlist nl[] = { { NULL }, { NULL }, { NULL }, };


    /* Check for the correct number of arguments */

    if(argc != 3) {
        printf("Usage:\n%s "
         " \n\n", argv[0]);

        printf("See /usr/src/sys/sys/syscall.h for syscall numbers"
         " \n");

        exit(0);
    }


    /* Find the syscall */

    nl[0].n_name = "sysent";
    nl[1].n_name = argv[1];
    callnum = atoi(argv[2]);

    printf("Finding syscall %d: %s\n\n", callnum, argv[1]);

    /* Initialize kernel virtual memory access */

    kd = kvm_openfiles(NULL, NULL, NULL, O_RDWR, errbuf);
    if(kd == NULL) {
        fprintf(stderr, "ERROR: %s\n", errbuf);
        exit(-1);
    }

    /* Find the addresses */

    if(kvm_nlist(kd, nl) < 0) {
        fprintf(stderr, "ERROR: %s\n", kvm_geterr(kd));
        exit(-1);
    }

    if(!nl[0].n_value) {
        fprintf(stderr, "ERROR: %s not found (fubar?)\n"
            , nl[0].n_name);
        exit(-1);
    }
    else {
        printf("%s is 0x%x at 0x%x\n", nl[0].n_name, nl[0].n_type
         , nl[0].n_value);
    }

    if(!nl[1].n_value) {
        fprintf(stderr, "ERROR: %s not found\n", nl[1].n_name);
        exit(-1);
    }


    /* Calculate the address */

    addr = nl[0].n_value + callnum * sizeof(struct sysent);


    /* Print out location */

    if(kvm_read(kd, addr, &call, sizeof(struct sysent)) < 0) {
        fprintf(stderr, "ERROR: %s\n", kvm_geterr(kd));
        exit(-1);
    }
    else {
        printf("sysent[%d] is at 0x%x and will execute function"
         " located at 0x%x\n", callnum, addr, call.sy_call);
    }

    if(kvm_close(kd) < 0) {
        fprintf(stderr, "ERROR: %s\n", kvm_geterr(kd));
        exit(-1);
    }

    exit(0);
}



看到代码估计有些会乐了,那不是所有在内存中的标识符,都可以找到了?答案是肯定的。

看看怎么使用吧,

ghost@slavetwo:~#ls
find_syscall.c
ghost@slavetwo:~#gcc -o find_syscall find_syscall.c -lkvm
ghost@slavetwo:~#ls
find_syscall find_syscall.c
ghost@slavetwo:~#sudo ./find_syscall
Password:
Usage:
./find_syscall

See /usr/src/sys/sys/syscall.h for syscall numbers
ghost@slavetwo:~#sudo ./find_syscall mkdir 136
Finding syscall 136: mkdir

sysent is 0x4 at 0xc06dc840
sysent[136] is at 0xc06dcc80 and will execute function located at 0xc0541900
是不是想要的结果了。呵呵,偷着乐吧。

阅读(2061) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~