分类: 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
是不是想要的结果了。呵呵,偷着乐吧。