1
0

syscall.c 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. /*
  2. * syscall.c
  3. *
  4. * System call "stealing" sample.
  5. *
  6. * Disables page protection at a processor level by
  7. * changing the 16th bit in the cr0 register (could be Intel specific)
  8. *
  9. * Based on example by Peter Jay Salzman and
  10. * https://bbs.archlinux.org/viewtopic.php?id=139406
  11. */
  12. #include <linux/delay.h>
  13. #include <linux/kernel.h>
  14. #include <linux/module.h>
  15. #include <linux/moduleparam.h> /* which will have params */
  16. #include <linux/syscalls.h>
  17. #include <linux/unistd.h> /* The list of system calls */
  18. /*
  19. * For the current (process) structure, we need
  20. * this to know who the current user is.
  21. */
  22. #include <linux/sched.h>
  23. #include <linux/uaccess.h>
  24. unsigned long **sys_call_table;
  25. unsigned long original_cr0;
  26. /*
  27. * UID we want to spy on - will be filled from the
  28. * command line
  29. */
  30. static int uid;
  31. module_param(uid, int, 0644);
  32. /*
  33. * A pointer to the original system call. The reason
  34. * we keep this, rather than call the original function
  35. * (sys_open), is because somebody else might have
  36. * replaced the system call before us. Note that this
  37. * is not 100% safe, because if another module
  38. * replaced sys_open before us, then when we're inserted
  39. * we'll call the function in that module - and it
  40. * might be removed before we are.
  41. *
  42. * Another reason for this is that we can't get sys_open.
  43. * It's a static variable, so it is not exported.
  44. */
  45. asmlinkage int (*original_call)(const char *, int, int);
  46. /*
  47. * The function we'll replace sys_open (the function
  48. * called when you call the open system call) with. To
  49. * find the exact prototype, with the number and type
  50. * of arguments, we find the original function first
  51. * (it's at fs/open.c).
  52. *
  53. * In theory, this means that we're tied to the
  54. * current version of the kernel. In practice, the
  55. * system calls almost never change (it would wreck havoc
  56. * and require programs to be recompiled, since the system
  57. * calls are the interface between the kernel and the
  58. * processes).
  59. */
  60. asmlinkage int our_sys_open(const char *filename, int flags, int mode)
  61. {
  62. int i = 0;
  63. char ch;
  64. /*
  65. * Report the file, if relevant
  66. */
  67. pr_info("Opened file by %d: ", uid);
  68. do {
  69. get_user(ch, filename + i);
  70. i++;
  71. pr_info("%c", ch);
  72. } while (ch != 0);
  73. pr_info("\n");
  74. /*
  75. * Call the original sys_open - otherwise, we lose
  76. * the ability to open files
  77. */
  78. return original_call(filename, flags, mode);
  79. }
  80. static unsigned long **aquire_sys_call_table(void)
  81. {
  82. unsigned long int offset = PAGE_OFFSET;
  83. unsigned long **sct;
  84. while (offset < ULLONG_MAX) {
  85. sct = (unsigned long **) offset;
  86. if (sct[__NR_close] == (unsigned long *) ksys_close)
  87. return sct;
  88. offset += sizeof(void *);
  89. }
  90. return NULL;
  91. }
  92. static int __init syscall_start(void)
  93. {
  94. if (!(sys_call_table = aquire_sys_call_table()))
  95. return -1;
  96. original_cr0 = read_cr0();
  97. write_cr0(original_cr0 & ~0x00010000);
  98. /* keep track of the original open function */
  99. original_call = (void *) sys_call_table[__NR_open];
  100. /* use our open function instead */
  101. sys_call_table[__NR_open] = (unsigned long *) our_sys_open;
  102. write_cr0(original_cr0);
  103. pr_info("Spying on UID:%d\n", uid);
  104. return 0;
  105. }
  106. static void __exit syscall_end(void)
  107. {
  108. if (!sys_call_table) {
  109. return;
  110. }
  111. /*
  112. * Return the system call back to normal
  113. */
  114. if (sys_call_table[__NR_open] != (unsigned long *) our_sys_open) {
  115. pr_alert("Somebody else also played with the ");
  116. pr_alert("open system call\n");
  117. pr_alert("The system may be left in ");
  118. pr_alert("an unstable state.\n");
  119. }
  120. write_cr0(original_cr0 & ~0x00010000);
  121. sys_call_table[__NR_open] = (unsigned long *) original_call;
  122. write_cr0(original_cr0);
  123. msleep(2000);
  124. }
  125. module_init(syscall_start);
  126. module_exit(syscall_end);
  127. MODULE_LICENSE("GPL");