add netbsd nl(1)
[rofl0r-hardcore-utils.git] / kmem_sym_patch.c
blobd41ce4e06ec8ce38eecf0522769b0afdb9c5f6bb
1 #include <stdio.h>
2 #include <fcntl.h>
3 #include <stdlib.h>
4 #include <string.h>
5 #include <unistd.h>
6 #include <ctype.h>
7 #include <signal.h>
9 static int open_kmem(int rdwr) {
10 int fd = open("/dev/kmem", rdwr ? O_RDWR : O_RDONLY);
11 return fd;
14 static int seek_kmem(int fd, off_t offset) {
15 if(-1==lseek(fd, offset, SEEK_SET)) {
16 perror("lseek");
17 return 0;
19 return 1;
22 static int find_sym(const char *symname, unsigned long *off, unsigned long *end) {
23 FILE *f = fopen("/proc/kallsyms", "r");
24 if(!f) return 0;
25 char buf[256];
26 size_t l = strlen(symname);
27 int succ = 0;
28 while(fgets(buf, sizeof buf, f)) {
29 char* p = buf;
30 if(succ) {
31 if(1!=sscanf(p, "%lx", end)) succ = 0;
32 goto ret;
34 while(*p && *p != ' ') p++;
35 p+=1;
36 if(*p != 'D' && *p != 'T') continue;
37 p+=2;
38 if(!strncmp(p, symname, l)) {
39 p=buf;
40 while(isspace(*p))p++;
41 if(1!=sscanf(p, "%lx", off)) goto ret;
42 succ=1;
45 ret:
46 fclose(f);
47 return succ;
50 static int syntax() {
51 puts("syntax: kernelpatch funcname payload [offset]\n"
52 "where payload is a hexadecimal string containing the new code\n"
53 "an optional offset into the function may be given to apply a selective patch\n");
54 return 1;
57 static void payload_from_hex(const char* s, unsigned char *pl) {
58 static const char hx[]="0123456789abcdef";
59 while(*s) {
60 *pl = ((strchr(hx, tolower(s[0])) - hx) << 4) | (strchr(hx, tolower(s[1])) - hx);
61 pl++;
62 s+=2;
66 int main(int argc, char **argv){
67 unsigned long off, end, user_off = 0;
68 if(argc < 3 || argc > 4) return syntax();
69 if(argc == 4) user_off = atoi(argv[3]);
70 size_t l = strlen(argv[2]);
71 if(l & 1) return syntax();
72 l=l/2;
73 unsigned char payload[l];
74 payload_from_hex(argv[2], payload);
76 if(!find_sym(argv[1], &off, &end)) {
77 puts("couldnt find offsets\n");
78 return 1;
80 off+=user_off;
81 if(l > end-off) {
82 puts("error: payload greater than existing code");
83 return 1;
86 int fd = open_kmem(1);
87 if(fd == -1) {
88 puts("couldnt open kmem");
89 return 1;
91 if(!seek_kmem(fd, off)) {
92 puts("kmem seek failed");
93 close(fd);
94 return 1;
96 int err = 0;
97 if(l != write(fd, payload, l)) {
98 err = 1;
99 puts("error writing payload");
102 close(fd);
104 return err;