远程线程注入

Posted boqingchi

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了远程线程注入相关的知识,希望对你有一定的参考价值。

分为Dll注入和代码注入,优缺点

  • 代码注入: 是没有全局变量和没有使用IAT表的硬编码,放到哪里都能执行。
  • 优点:不易被发现。 缺点:自己写函数十分麻烦。
  • dll注入: 模块注入一整个进去
  • 优点:全局函数IAT都在模块中,使用方便。缺点:容易被检测,特征太明显。

CreateThread和CreateRemoteThread 唯一不同的地方

技术图片

远程线程注入原理

  • B 往 A注入需要提供线程函数的地址(需要在 A 中),和线程函数的参数(需要在 A 中)
    技术图片

  • 线程函数是有格式要求的,返回类型是 DWORD ,调用约定是Win Api默认调用约定stdcall,参数是 void* 指针。满足这个要求才能调用,有个偶然 LoadLibrary 这个函数 返回值是个句(DWORD),参数虽然不是void* 但是可以转成void* 用。

  • 所以在进程B中创建远程线程以后,直接把线程函数地址指向 LoadLibrary (A 进程中的地址),这个地址直接显式调用即可,因为这个模块是每个程序一定加载的,地址一样的。

  • LoadLibrary 需要一个参数,一个字符串地址,需要用 WriteProcessMemory 写入到 进程 A 中。就获得地址了。

  • 自己执行 LoadLibrary 会获得一个模块句柄,远程线程注入可以通过 GetExitCodeThread 获取线程退出码获取。

注入流程

1 打开进程 OpenProcess
2 远程进程中申请空间 VirtualAllocEx
3 向远程进程写入数据 WriteProcessMemory
4 在远程进程中创建远程线程 CreateRemoteThread
5 等待线程结束返回 WaitForSingleObject
6 释放空间 VirtualFreeEx

dll注入代码

#include"pch.h"
#include<Windows.h>
#include<tlhelp32.h>
#include <assert.h>
#include<tchar.h>
#include <iostream>



//获取进程name的ID
DWORD GetPid(LPTSTR name)
{
	HANDLE hProcSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);        //获取进程快照句柄
	assert(hProcSnap != INVALID_HANDLE_VALUE);                                 //判断是否打开成功
	PROCESSENTRY32 pe32; 
	pe32.dwSize = sizeof(PROCESSENTRY32);
	BOOL flag = Process32First(hProcSnap, &pe32);                          //获取列表的第一个进程
	while (flag)
	{
		if (!_tcscmp(pe32.szExeFile, name))
		{
			CloseHandle(hProcSnap);
			return pe32.th32ProcessID;//pid
		}
		flag = Process32Next(hProcSnap, &pe32);//获取下一个进程
	}
	CloseHandle(hProcSnap);
	printf("没有找到相关进程");
	return 0;
}


// 提权函数:提升为DEBUG权限
BOOL EnableDebugPrivilege()
{
	HANDLE hToken;
	BOOL fOk = FALSE;
	if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken))
	{
		TOKEN_PRIVILEGES tp;
		tp.PrivilegeCount = 1;
		LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &tp.Privileges[0].Luid);

		tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
		AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(tp), NULL, NULL);

		fOk = (GetLastError() == ERROR_SUCCESS);
		CloseHandle(hToken);
	}
	return fOk;
}

int main()
{
	EnableDebugPrivilege();
	printf("输入要注入的进程名(.exe):
");
	char cname[260] = {};
	scanf_s("%s", cname, 260);

	printf("输入dll路径(\\)");
	char cpath[260];
	scanf_s("%s", cpath,260);


	DWORD Pid = 0;
	Pid = GetPid((LPTSTR)cname);

	// 用PID打开进程 参数1:权限 参数2:是否继承 参数3:PID
	HANDLE Handle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, Pid);
	

	//2. 远程进程中申请空间  
	//参数1:进程句柄 参数2:起始地址(NULL函数决定分配到哪)
	//参数3:要分配的大小(不够一页分一页) 参数4:内存分配类型(保留提交) 参数5:内存保护
	LPVOID Address = VirtualAllocEx(Handle, NULL, 0x100, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);


	//3.向远程进程写入数据
	//也就是LoadLibrary的参数,即Dll的地址
	//不同的系统使用到的 LoadLibrary 可能是 A/W 的,需要和字符串匹配
	DWORD RealWrite = 0; //实际写入的地址
	// 参数1:进程句柄 参数2:写入数据的起始地址 参数3:写入的数据 参数4:写入字节数 参数5:实际写入字节数
	WriteProcessMemory(Handle, Address, cpath, strlen(cpath)+1, &RealWrite);


	//4. 在目标进程内创建远程线程
	//线程的起始位置是 LoadLibrary,在Windows下,所有 Windows API 在不同进程中的函数地址都是相同
	//参数1:进程句柄 参数2:安全描述符(为0默认) 参数3:堆栈初始大小(为0默认) 
	//参数4:指向由线程执行的,类型为LPTHREAD_START_ROUTINE的应用程序定义的函数指针
	//参数5:函数的参数指针 参数6:控制线程创建的标志(为0立即执行) 参数7:指向接收线程标识符的变量的指针(为0不接收)
	HANDLE Thread = CreateRemoteThread(Handle, NULL, NULL, (LPTHREAD_START_ROUTINE)LoadLibraryA, Address, NULL, NULL);


	//5.等待远程线程执行完毕
	WaitForSingleObject(Thread, -1);

	//6. 释放空间
	//可以选择是否释放注入的模块
	VirtualFreeEx(Handle, Address, NULL, MEM_RELEASE);


	system("pause");
	//释放句柄
	CloseHandle(Thread);
	CloseHandle(Handle);
	return 0;




}

dll注入使用的dll代码

  • 仅弹框
// dllmain.cpp : 定义 DLL 应用程序的入口点。
#include "stdafx.h"
#include <windows.h>
BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
                     )
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:            //Dll被加载时
		MessageBox(NULL, L"感染成功", L"潜伏", MB_OK);
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
        break;
    }
    return TRUE;
}








以上是关于远程线程注入的主要内容,如果未能解决你的问题,请参考以下文章

远程线程注入

远程线程注入

远程线程DLL注入, 如何释放DLL和结束DLL的线程

远程线程的注入 PE的修正

JNA实现远程线程注入

远程线程注入遇到的问题