Advertisement
Guest User

Untitled

a guest
Apr 23rd, 2018
80
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.03 KB | None | 0 0
  1. #include <linux/module.h>
  2. #include <linux/kernel.h>
  3. #include <linux/init.h>
  4. #include <linux/syscalls.h>
  5. #include <linux/string.h>
  6.  
  7.  
  8. MODULE_LICENSE("GPL");
  9. MODULE_AUTHOR("Kamal Marhubi");
  10. MODULE_DESCRIPTION("Rickroll module");
  11.  
  12. static char *rickroll_filename = "/home/bork/media/music/Rick Astley - Never Gonna Give You Up.mp3";
  13.  
  14. /*
  15. * Set up a module parameter for the filename. The arguments are variable name,
  16. * type, and permissions The third argument is the permissions for the parameter
  17. * file in sysfs, something like
  18. *
  19. * /sys/module/<module_name>/parameters/<parameter_name>
  20. *
  21. * We're setting it writeable by root so it can be modified without reloading
  22. * the module.
  23. */
  24. module_param(rickroll_filename, charp, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
  25. MODULE_PARM_DESC(rickroll_filename, "The location of the rick roll file");
  26.  
  27.  
  28. /*
  29. * cr0 is an x86 control register, and the bit we're twiddling here controls
  30. * the write protection. We need to do this because the area of memory
  31. * containing the system call table is write protected, and modifying it would
  32. * case a protection fault.
  33. */
  34. #define DISABLE_WRITE_PROTECTION (write_cr0(read_cr0() & (~ 0x10000)))
  35. #define ENABLE_WRITE_PROTECTION (write_cr0(read_cr0() | 0x10000))
  36.  
  37.  
  38. static unsigned long **find_sys_call_table(void);
  39. asmlinkage long rickroll_open(const char __user *filename, int flags, umode_t mode);
  40.  
  41. asmlinkage long (*original_sys_open)(const char __user *, int, umode_t);
  42. asmlinkage unsigned long **sys_call_table;
  43.  
  44.  
  45. static int __init rickroll_init(void)
  46. {
  47. if(!rickroll_filename) {
  48. printk(KERN_ERR "No rick roll filename given.");
  49. return -EINVAL; /* invalid argument */
  50. }
  51.  
  52. sys_call_table = find_sys_call_table();
  53.  
  54. if(!sys_call_table) {
  55. printk(KERN_ERR "Couldn't find sys_call_table.\n");
  56. return -EPERM; /* operation not permitted; couldn't find general error */
  57. }
  58.  
  59. /*
  60. * Replace the entry for open with our own function. We save the location
  61. * of the real sys_open so we can put it back when we're unloaded.
  62. */
  63. DISABLE_WRITE_PROTECTION;
  64. original_sys_open = (void *) sys_call_table[__NR_open];
  65. sys_call_table[__NR_open] = (unsigned long *) rickroll_open;
  66. ENABLE_WRITE_PROTECTION;
  67.  
  68. printk(KERN_INFO "Never gonna give you up!\n");
  69. return 0; /* zero indicates success */
  70. }
  71.  
  72.  
  73. /*
  74. * Our replacement for sys_open, which forwards to the real sys_open unless the
  75. * file name ends with .mp3, in which case it opens the rick roll file instead.
  76. */
  77. asmlinkage long rickroll_open(const char __user *filename, int flags, umode_t mode)
  78. {
  79. int len = strlen(filename);
  80.  
  81. /* See if we should hijack the open */
  82. if(strcmp(filename + len - 4, ".mp3")) {
  83. /* Just pass through to the real sys_open if the extension isn't .mp3 */
  84. return (*original_sys_open)(filename, flags, mode);
  85. } else {
  86. /* Otherwise we're going to hijack the open */
  87. mm_segment_t old_fs;
  88. long fd;
  89.  
  90. /*
  91. * sys_open checks to see if the filename is a pointer to user space
  92. * memory. When we're hijacking, the filename we pass will be in kernel
  93. * memory. To get around this, we juggle some segment registers. I
  94. * believe fs is the segment used for user space, and we're temporarily
  95. * changing it to be the segment the kernel uses.
  96. *
  97. * An alternative would be to use read_from_user() and copy_to_user()
  98. * and place the rickroll filename at the location the user code passed
  99. * in, saving and restoring the memory we overwrite.
  100. */
  101. old_fs = get_fs();
  102. set_fs(KERNEL_DS);
  103.  
  104. /* Open the rickroll file instead */
  105. fd = (*original_sys_open)(rickroll_filename, flags, mode);
  106.  
  107. /* Restore fs to its original value */
  108. set_fs(old_fs);
  109.  
  110. return fd;
  111. }
  112. }
  113.  
  114.  
  115. static void __exit rickroll_cleanup(void)
  116. {
  117. printk(KERN_INFO "Ok, now we're gonna give you up. Sorry.\n");
  118.  
  119. /* Restore the original sys_open in the table */
  120. DISABLE_WRITE_PROTECTION;
  121. sys_call_table[__NR_open] = (unsigned long *) original_sys_open;
  122. ENABLE_WRITE_PROTECTION;
  123. }
  124.  
  125.  
  126. /*
  127. * Finds the system call table's location in memory.
  128. *
  129. * This is necessary because the sys_call_table symbol is not exported. We find
  130. * it by iterating through kernel space memory, and looking for a known system
  131. * call's address. We use sys_close because all the examples I saw used
  132. * sys_close. Since we know the offset of the pointer to sys_close in the table
  133. * (__NR_close), we can get the table's base address.
  134. */
  135. static unsigned long **find_sys_call_table() {
  136. unsigned long offset;
  137. unsigned long **sct;
  138.  
  139. for(offset = PAGE_OFFSET; offset < ULLONG_MAX; offset += sizeof(void *)) {
  140. sct = (unsigned long **) offset;
  141.  
  142. if(sct[__NR_close] == (unsigned long *) sys_close)
  143. return sct;
  144. }
  145.  
  146. /*
  147. * Given the loop limit, it's somewhat unlikely we'll get here. I don't
  148. * even know if we can attempt to fetch such high addresses from memory,
  149. * and even if you can, it will take a while!
  150. */
  151. return NULL;
  152. }
  153.  
  154.  
  155. module_init(rickroll_init);
  156. module_exit(rickroll_cleanup);
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement