9 static int open_kmem(int rdwr
) {
10 int fd
= open("/dev/kmem", rdwr
? O_RDWR
: O_RDONLY
);
14 static int seek_kmem(int fd
, off_t offset
) {
15 if(-1==lseek(fd
, offset
, SEEK_SET
)) {
22 static int find_sym(const char *symname
, unsigned long *off
, unsigned long *end
) {
23 FILE *f
= fopen("/proc/kallsyms", "r");
26 size_t l
= strlen(symname
);
28 while(fgets(buf
, sizeof buf
, f
)) {
31 if(1!=sscanf(p
, "%lx", end
)) succ
= 0;
34 while(*p
&& *p
!= ' ') p
++;
36 if(*p
!= 'D' && *p
!= 'T') continue;
38 if(!strncmp(p
, symname
, l
)) {
40 while(isspace(*p
))p
++;
41 if(1!=sscanf(p
, "%lx", off
)) goto ret
;
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");
57 static void payload_from_hex(const char* s
, unsigned char *pl
) {
58 static const char hx
[]="0123456789abcdef";
60 *pl
= ((strchr(hx
, tolower(s
[0])) - hx
) << 4) | (strchr(hx
, tolower(s
[1])) - hx
);
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();
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");
82 puts("error: payload greater than existing code");
86 int fd
= open_kmem(1);
88 puts("couldnt open kmem");
91 if(!seek_kmem(fd
, off
)) {
92 puts("kmem seek failed");
97 if(l
!= write(fd
, payload
, l
)) {
99 puts("error writing payload");