summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJason A. Donenfeld <Jason@zx2c4.com>2012-04-02 05:15:43 +0200
committerJason A. Donenfeld <Jason@zx2c4.com>2012-04-02 05:15:43 +0200
commit8ed56c37de24088052fe7a0eed4cd96bc38b50dc (patch)
treefa7b5016cff65c961aff9887ee89745b2b66594c
parentInitial commit. (diff)
downloadandroid-connect-blinker-8ed56c37de24088052fe7a0eed4cd96bc38b50dc.tar.xz
android-connect-blinker-8ed56c37de24088052fe7a0eed4cd96bc38b50dc.zip
Hook the ops table.
-rw-r--r--Makefile2
-rw-r--r--hook-ip.c41
-rw-r--r--inet-connect-hook.c49
3 files changed, 50 insertions, 42 deletions
diff --git a/Makefile b/Makefile
index 9bfe676..fc4b92f 100644
--- a/Makefile
+++ b/Makefile
@@ -1,4 +1,4 @@
-obj-m := hook-ip.o
+obj-m := inet-connect-hook.o
KDIR := /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
diff --git a/hook-ip.c b/hook-ip.c
deleted file mode 100644
index 290e463..0000000
--- a/hook-ip.c
+++ /dev/null
@@ -1,41 +0,0 @@
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/unistd.h>
-#include <linux/socket.h>
-#include <linux/sched.h>
-
-unsigned long *syscall_table = (unsigned long *)0xffffffff818001e0;
-void (*set_pages_rw)(struct page *page, int numpages) = (void *)0xffffffff8102be40;
-void (*set_pages_ro)(struct page *page, int numpages) = (void *)0xffffffff8102be00;
-
-asmlinkage long (*original_connect)(int, struct sockaddr __user *, int);
-asmlinkage long new_connect(int fd, struct sockaddr __user *uservaddr, int addrlen)
-{
- printk(KERN_ALERT "Hooked connect.");
- return (*original_connect)(fd, uservaddr, addrlen);
-}
-static void* set_syscall(int syscall, void *new_function)
-{
- void *original;
- struct page *sys_call_page;
- sys_call_page = virt_to_page(syscall_table);
- set_pages_rw(sys_call_page, 1);
- original = (void *)syscall_table[syscall];
- syscall_table[syscall] = (unsigned long)new_function;
- set_pages_ro(sys_call_page, 1);
- return original;
-}
-static int init(void)
-{
- original_connect = set_syscall(__NR_connect, new_connect);
- return 0;
-}
-static void exit(void)
-{
- set_syscall(__NR_connect, original_connect);
-}
-module_init(init);
-module_exit(exit);
-
-
diff --git a/inet-connect-hook.c b/inet-connect-hook.c
new file mode 100644
index 0000000..caca0d2
--- /dev/null
+++ b/inet-connect-hook.c
@@ -0,0 +1,49 @@
+#include <linux/module.h>
+#include <linux/net.h>
+#include <linux/mm.h>
+
+extern struct proto_ops inet_stream_ops;
+
+static void disable_page_protection(void)
+{
+ unsigned long value;
+ asm volatile("mov %%cr0,%0" : "=r" (value));
+ if (value & 0x00010000) {
+ value &= ~0x00010000;
+ asm volatile("mov %0,%%cr0": : "r" (value));
+ }
+}
+static void enable_page_protection(void)
+{
+ unsigned long value;
+ asm volatile("mov %%cr0,%0" : "=r" (value));
+ if (!(value & 0x00010000)) {
+ value |= 0x00010000;
+ asm volatile("mov %0,%%cr0": : "r" (value));
+ }
+}
+
+int (*old_connect)(struct socket *sock, struct sockaddr *vaddr, int sockaddr_len, int flags);
+int connect(struct socket *sock, struct sockaddr *vaddr, int sockaddr_len, int flags)
+{
+ printk(KERN_ALERT "Hooked connect.");
+ return (*old_connect)(sock, vaddr, sockaddr_len, flags);
+}
+static int init(void)
+{
+ old_connect = inet_stream_ops.connect;
+ disable_page_protection();
+ inet_stream_ops.connect = connect;
+ enable_page_protection();
+ return 0;
+}
+static void exit(void)
+{
+ disable_page_protection();
+ inet_stream_ops.connect = old_connect;
+ enable_page_protection();
+}
+module_init(init);
+module_exit(exit);
+
+