A simple activity monitor with /dev/random

2012, Nov 24    

Today I was performing some tests in the random number generators of some browsers and found, by chance, this mail sent to Bugtraq by Michal Zalewsky called “Unix entropy source can be used for keystroke timing attacks”. While the idea of Michal is very good, I failed to find a reliable way of doing it in my house computer after some time (well, honestly, after just 1 hour…). However, a more simpler idea come to my mind: if /dev/random blocks when the entropy pool is empty and most of the events are generated when mouse or keyboard events happens, at least, I can write quite easily an activity monitor based on /dev/random.

A simple activity monitor

The idea is very simple: read all available data in /dev/random and then, depending on the intervals new data is available, try to determine if the mouse or keyboard is being used. For this I created the following simple Python script:

#!/usr/bin/python
  1.  
  2. import time
  3. import select
  4.  
  5. ACTIVITY_MOUSE =
  6. ACTIVITY_KEYBOARD = 1
  7.  
  8. def wait_for_activity():
  9.   """ Returns (0, time) for mouse and (1, time) for keyboard activity.
  10.      Note, however, that the metrics are just a guess. """
  11.   started = True
  12.  
  13.   f = open("/dev/random", "rb")
  14.   f.seek(2, )
  15.  
  16.   keyboard =
  17.   mouse =
  18.   ret = None
  19.  
  20.   while ret is None:
  21.     t = time.time()
  22.  
  23.     select.select([f], [], [])        
  24.     f.read(8)
  25.  
  26.     t = time.time()-t
  27.     if started:
  28.        started = False
  29.        continue
  30.  
  31.     if t <= 1:
  32.       if mouse >= 1:
  33.           ret = (, t)
  34.       else:
  35.         mouse += 1
  36.         keyboard -= 1
  37.     elif t <= 5:
  38.       if keyboard >= 1:
  39.           ret = (1, t)
  40.       else:
  41.         keyboard += 1
  42.         mouse -= 1
  43.     else:
  44.       keyboard = mouse =
  45.  
  46.   f.close()
  47.   return ret
  48.  
  49. def main():
  50.   while 1:
  51.     act = wait_for_activity()
  52.     if act[] == ACTIVITY_MOUSE:
  53.       print "MOUSE ACTIVITY DETECTED", act[1]
  54.     else:
  55.       print "KEYBOARD ACTIVITY DETECTED", act[1]
  56.  
  57. if __name__ == "__main__":
  58.   main()

Execute this script and see if it works for you. In my case, for reading 8 bytes it typically takes 1 second or less when mouse events happens (normal stuff: browsing, reading mail, etc…) and 5 seconds or less for keystrokes. Some of the problems I noticed are, for example, that often the script thinks that when I’m writing mouse events are happening, when they are not (I think I type too fast for my script). In any case, more or less (in my home computer, at least) it’s working.

For next posts, hopefully, I’ll be able to write a working program for the (old) idea of Michal Zalewsky but, meanwhile, this is what I have working. I hope you find it interesting or useful. Bye!