首页
社区
课程
招聘
[原创]纯C++编写Win32/X64通用Shellcode注入csrss进程.
发表于: 2015-8-8 04:26 38211

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

2015-8-8 04:26
38211
这是做的一些研究,觉得没什么用处,人生不应该把精力放在这些小打小闹的垃圾玩意身上;先讲一下文章的主题这样做的目的,这样做免去了用汇编代码限制,纯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;
}


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

[课程]Android-CTF解题方法汇总!

上传的附件:
收藏
免费 9
支持
分享
最新回复 (30)
雪    币: 44229
活跃值: (19965)
能力值: (RANK:350 )
在线值:
发帖
回帖
粉丝
2
IE首页保护算法逆向工程?
东西先不要删除,如果写的好,版主会移到软件调试版块去的
2015-8-8 17:54
2
雪    币: 18
活跃值: (1009)
能力值: ( LV7,RANK:110 )
在线值:
发帖
回帖
粉丝
3
顶起来,人生必须通过努力才能得到自己想要、喜欢的东西.
2015-8-13 20:51
1
雪    币: 10
活跃值: (25)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
rel
4
占坑以待
2015-8-14 02:37
1
雪    币: 878
活跃值: (496)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
5
小东西成就大事物
2015-8-16 11:34
0
雪    币: 248
活跃值: (3789)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
围观一下,顶起来
2015-8-16 12:08
0
雪    币: 42
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
人生不应该把精力放在这些小打小闹的垃圾玩意身上
2015-8-16 14:13
0
雪    币: 16444
活跃值: (2463)
能力值: ( LV9,RANK:147 )
在线值:
发帖
回帖
粉丝
8
楼上偏了,.感谢楼主分享.不要小看一些小事物,积累起来可能成就无穷的力量.
2015-8-16 14:51
0
雪    币: 242
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
附件缺少头文件啊,大神。
main.cc(2): fatal error C1083: 无法打开包括文件: “base/component_name.h”: No such file or directory
2015-8-16 15:54
0
雪    币: 263
活跃值: (64)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
技术很重要,修养也很重要,老板眼中都只是工具,相煎何急呢
2015-8-18 09:45
0
雪    币: 8865
活跃值: (2379)
能力值: ( LV12,RANK:760 )
在线值:
发帖
回帖
粉丝
11
点赞~csrss注入还是被人发出来了~
2015-8-18 11:27
0
雪    币: 239
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
12
错误        1        error C1083: 无法打开包括文件: “base/component_name.h”: No such file or directory        C:\Users\link\Desktop\bootldr\dllmain.cc        3        1        bootldr
2015-8-18 12:21
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
13
mark
2015-8-18 14:36
0
雪    币: 144
活跃值: (335)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
14
膜拜 csrss注入
2015-8-23 21:49
0
雪    币: 36
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
15
感谢楼主分享
2015-8-26 18:28
0
雪    币: 630
活跃值: (570)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
16
感谢楼主分享~
2016-1-9 09:42
0
雪    币: 260
活跃值: (34)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
17
启动远程线程失败了。。
2016-3-7 10:01
0
雪    币: 3836
活跃值: (4142)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
18
你这逗逼
2016-4-1 23:04
0
雪    币: 137
活跃值: (115)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
19
报个要求版本12,你当前版本为4的错误
2016-4-3 11:11
0
雪    币: 235
活跃值: (23)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
20
打开csrss进程失败呀?如何打开csrss进程
2016-9-27 09:25
0
雪    币: 115
活跃值: (23)
能力值: (RANK:20 )
在线值:
发帖
回帖
粉丝
21
你就想大家都不发,你们统治内核!!
2016-11-18 21:05
0
雪    币: 115
活跃值: (23)
能力值: (RANK:20 )
在线值:
发帖
回帖
粉丝
22
兄弟,六个联系方式把。我有事情请教你!
2016-11-18 21:06
0
雪    币: 10050
活跃值: (4056)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
23
感谢楼主分享。
2016-11-18 21:56
0
雪    币: 40
活跃值: (303)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
24
谢谢,易编译出来竟然免杀
2016-11-20 22:57
0
雪    币: 1
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
25
能说说 这个注入后有什么用.可以做什么坏事呢....这进程权限很高的啊
2016-11-20 23:11
0
游客
登录 | 注册 方可回帖
返回
//