<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>

    祥云杯2021 Windows R0題 Rev_APC

    VSole2021-09-04 15:46:04

     

    一看題目給出的sys文件,可以確定是本人最擅長的Windows內核和注入相關題目,必須要把這個驅動安排的明明白白的。

    附件已上傳對應的i64文件,把驅動拖入IDA分析,發現創建了通信設備。

    解密加密的dll文件數據,釋放到C:\WINDOWS\TEMP\InjectDLL.dll。

    注冊了minifilter,暫時沒有發現這個minifilter有什么用,可能是配合LoadImage回調里的計算文件名用的。

    還另外創建了LPC端口用來與r3通信。

    創建一個SystemThread監聽LPC端口:

    創建了進程通知回調和LoadImage回調:

    先來看進程通知回調:

    insert_contextlist這邊取了一波進程映像名字符串的hash,如果是explorer.exe,就設置context+301的flag,其實就是指定注入explorer.exe。

    來看LoadImage回調。

    如果當前執行該回調的進程是explorer.exe,則插入一個內核模式apc:

    fntable[0x100]的地方是執行注入r3的函數,所以文件名算出來的合必須為0x100。

    注入shellcode的過程是用ZwMapViewOfSection來申請R3注入代碼所需的RWX內存,然后插入用戶模式APC,異步執行R3注入代碼。

    R3 shellcode:

    至此,該驅動的基本功能已分析完畢。

    構建調試環境條件

    因為要求注入的是explorer.exe,但是注入系統的explorer.exe會導致進程崩潰,所以我自己編譯了一份與explorer.exe映像名稱相同的exe來調試InjectDLL.dll。

    我這里預先計算出來了一個文件名來繞過Load。

    Image回調的限制

    分析InjectDLL.dll

    先Load了一個不存在的dll,調用了里面的"GetContentHash"函數:

    字符串"test"對應的hash為36F028580BB02CC8272A9A020F4200E346E276AE664E45EE80745574E2F5AB80,經過一番搜索后,可知這是SHA3-256算法。

    在線計算得出字符串'AkiraDDL'的SHA3-256值為9d5f741799d7e62274f01963516316d2eb6888b737bab0a2b0e1774e3b7389e5。

    手動編寫一個dll,導出GetContentHash函數,粗略cmp一下就行。

    創建設備與R0通信,然后再使用lpc和r0通信,這里的數據都是固定的,動態調試dump下來就行。

    這里的rand沒有設定隨機數種子,所以可以模擬出來每次的返回值。

     

    case里面是與驅動通信來加密buf的,將各個加密函數求出逆運算即可解密flag。

    flag : flag{Kmode_Umode_Communication!}

    解密代碼:

    #include 
    #include "windows.h"
    #include "intrin.h"
     
    void re_dec1(PCHAR b1, PCHAR b2) {
        char v9;
        char v8;
        for (int i = 0x1F; i >= 0; i--) {
            v9 = i;
            v8 = b1[i];
            b2[i] ^= v8;
            b1[i] -= 0x10;
        }
     
    }
    void re_dec2(PCHAR b1, PCHAR b2) {
        char v8 = 0;
        for (int i = 0x1F; i >= 0; i--) {
            char b1v = b1[i];
            _asm mov al, b1v;
            _asm ror al, 4;
            _asm mov v8, al;
            b2[i] ^= v8;
        }
        for (int i = 0x1F; i >= 0; i--) {
            b1[i] += 80;
        }
     
    }
    void re_dec3(PCHAR b1, PCHAR b2) {
        for (int i = 0x1F; i >= 0; i--) {
            b2[i] ^= b1[i];
        }
    }
    void re_dec4(PCHAR b1, PCHAR b2) {
        /*for (int i = 0xF; i >= 0; i--) {
            char v = b1[i * 2];
            b2[i * 2 + 1] ^= v >> 4;
            b2[i * 2] ^= v * 16;
     
        }*/
        BYTE* v8; // r8
        BYTE* fu_sz; // r10
        unsigned __int64 v10; // r9
        unsigned __int8 v_pbuf1; // cl
        v8 = (BYTE*)(b2 + 1);
        fu_sz = (BYTE*)-0x20;
        v10 = 0x10;// 0x10
        do
        {
            v_pbuf1 = v8[(DWORD64)fu_sz - 1];
            *v8 ^= v_pbuf1 >> 4;
            v8 += 2;
            *(v8 - 3) ^= 16 * v_pbuf1;
            --v10;
        } while (v10);
        for (int i = 0x1F; i >= 0; i--) {
            b1[i] += 80;
        }
    }
    void re_dec5(PCHAR b1, PCHAR b2) {
        for (int i = 0x1F; i >= 0; i--) {
            b2[i] ^= b1[i];
        }
        char* buf1_right = &b1[0x10];
        char* buf1_left = &b1[0x10 - 1];
        for (int i = 0xF; i >= 0; i--) {
            char temp = 0;
            temp = *buf1_right;
            *buf1_right = *buf1_left;
            *buf1_left = temp;
            buf1_left--;
            buf1_right++;
        }
     
        char* buf1_start = b1;
        char* buf1_end = &b1[0x20 - 1];
        for (int i = 0xF; i >= 0; i--) {
            char temp = 0;
            temp = *buf1_start;
            *buf1_start = *buf1_end;
            *buf1_end = temp;
            buf1_start++;
            buf1_end--;
        }
     
    }
    void re_dec6(PUCHAR b1, PUCHAR b2) {
        unsigned char v8 = 0;
        unsigned char v7 = 0;
        unsigned char v6 = 0;
        for (int i = 0x1F; i >= 0; i--) {
            if (b1[i] == 0x50)
                continue;
            if (b1[i] == 0x80)
                __debugbreak();
            if (b1[i] > 0x50 && b1[i] <= 0xCF) {
                v8 = b1[i];
                b1[i] += 0x30;
                b2[i] += v8;
            }
            else if (b1[i] > 0x20 && b1[i] <= 0x4F) {
                v7 = b1[i];
                b1[i] += 0x30;
                b2[i] ^= v7 >> 4;
            }
            else if (b1[i] > 0xD0 && b1[i] <= 0xFF) {
                v6 = b1[i];
                b1[i] += 0x50;
                b2[i] -= v6;
            }
     
        }
    }
     
    int main()
    {
        unsigned char pstatic[] = { 0xF5, 0x9A, 0xF7, 0xA1, 0xC4, 0xA7, 0xD6, 0x23, 0xE1, 0x28, 0xEF, 0xB8, 0xDE, 0x23, 0xE7, 0x2F };
        unsigned char pebuf[] = { 0xDC, 0xA7, 0xCA, 0x92, 0xFE, 0x9D, 0xED, 0xB8, 0x70, 0x29, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5, 0xE5 };
     
        unsigned char use_buf1[0x20] = { 0 };
        memcpy(use_buf1, pstatic, 0x10);
        memcpy(use_buf1 + 0x10, pebuf, 0x10);
     
        unsigned char use_buf2[0x20] = { 0 };
        *(ULONG64*)use_buf2 = 0x2F34A83A1B38C557;
        *(ULONG64*)(use_buf2 + 0x8) = 0xEE8F2F04E4C69739;
        *(ULONG*)(use_buf2 + 0x10) = 0x6780515E;
        *(ULONG*)(use_buf2 + 0x14) = 0x486FC924;
        *(ULONG*)(use_buf2 + 0x18) = 0xC7BD7F5B;
        *(ULONG*)(use_buf2 + 0x1C) = 0xEBC2C2B0;
        unsigned char all_buf[0x40] = { 0 };
        memcpy(all_buf, use_buf1, 0x20);
        memcpy(all_buf + 0x20, use_buf2, 0x20);
     
        char* pbuf1 = (char*)all_buf;
        char* pbuf2 = (char*)(all_buf + 0x20);
     
     
        int reverseidx[32] = { 0 };
        HMODULE hmod = LoadLibraryA("ucrtbase.dll");
        typedef int (*fnrand)();
        fnrand prand = (fnrand)GetProcAddress(hmod, "rand");
        for (int i = 0; i < 32; i++) {
            int v = prand() % 6;
            reverseidx[i] = v;
            printf("%d", v);
        }
        for (int j = 31; j >= 0; j--) {
            int i = reverseidx[j];
            switch (i)
            {
            case 0:
                re_dec1(pbuf1, pbuf2);
                break;
            case 1:
                re_dec2(pbuf1, pbuf2);
                break;
            case 2:
                re_dec3(pbuf1, pbuf2);
                break;
            case 3:
                re_dec4(pbuf1, pbuf2);
                break;
            case 4:
                re_dec5(pbuf1, pbuf2);
                break;
            case 5:
                re_dec6((PUCHAR)pbuf1, (PUCHAR)pbuf2);
                break;
            default:
                break;
            }
        }
     
    }
    
    charchar函數
    本作品采用《CC 協議》,轉載必須注明作者和本文鏈接
    無意中看到ch1ng師傅的文章覺得很有趣,不得不感嘆師傅太厲害了,但我一看那長篇的函數總覺得會有更騷的東西,所幸還真的有,借此機會就發出來一探究竟,同時也不得不感慨下RFC文檔的妙處,當然本文針對的技術也僅僅只是在流量層面上waf的繞過。Pre很神奇對吧,當然這不是終點,接下來我們就來一探究竟。前置這里簡單說一下師傅的思路部署與處理上傳war的servlet是?
    記一次網站滲透過程
    2022-09-13 08:37:27
    前幾天記錄某一次無意點開的一個小網站的滲透過程,幸運的是搭建平臺是phpstudy,cms是beecms,beecms有通用漏洞,然后去網上找了資料,成功getshell并獲取服務器權限。
    一、序言 記錄某一次無意點開的一個小網站的滲透過程,幸運的是搭建平臺是phpstudy,cms是beecms,beecms有通用漏洞,然后去網上找了資料,成功getshell并獲取服務器權限。 二、滲透過程 1. 無意點開一個網站,發現網站比較小,且看起來比較老,然后發現logo沒有改,于是乎去百度搜索這個cms,發現有通用漏洞,這里貼一個鏈接:Beecms 通用漏洞(https://lin
    釣魚小技巧-XLM
    2022-01-21 21:30:11
    隨后保存為啟用宏的文檔。而在實戰環境中,我們更關注的是能否執行我們的shellcode。
    前言最近一段時間在研究Android加殼和脫殼技術,其中涉及到了一些hook技術,于是將自己學習的一些hook技術進行了一下梳理,以便后面回顧和大家學習。主要是進行文本替換、宏展開、刪除注釋這類簡單工作。所以動態鏈接是將鏈接過程推遲到了運行時才進行。
    最近在分析JDK7u21的Gadgets,有兩個不解之處,閱讀前輩們的文章發現并未提起。1.為什么有的POC入口是LinkedHashSet,有的是HashSet,兩個都可以觸發嗎?
    依賴于特定硬件環境的固件無法完整模擬,需要hook掉其中依賴于硬件的函數。LD_PRELOAD的劫持對于特定函數的劫持技術分為動態注入劫持和靜態注入劫持兩種。網上針對LD_PRELOAD的劫持也有大量的描述
    這里根據紅日安全PHP-Audit-Labs對一些函數缺陷的分析,從PHP內核層面來分析一些函數的可利用的地方,標題所說的函數缺陷并不一定是函數本身的缺陷,也可能是函數在使用過程中存在某些問題,造成了漏洞,以下是對部分函數的分析
    關于堆棧ShellCode操作:基礎理論002-利用fs寄存器尋找當前程序dll的入口:從動態運行的程序中定位所需dll003-尋找大兵LoadLibraryA:從定位到的dll中尋找所需函數地址004-被截斷的shellCode:加解密,解決shellCode的零字截斷問題
    VSole
    網絡安全專家
      亚洲 欧美 自拍 唯美 另类