공부해요/리버싱_핵심원리

23. DLL 인젝션

yenas0 2024. 11. 4. 14:30
반응형

DLL 인젝션
DLL 인젝션은 실행 중인 다른 프로세스에 특정 DLL 파일을 강제로 삽입하는 기법. 이는 다른 프로세스로 하여금 LoadLibrary() API를 스스로 호출하도록 명령하여 사용자가 원하는 DLL을 로딩하도록 하는 방식

DLL 인젝션의 동작 원리

DLL 인젝션의 동작 원리는 외부에서 다른 프로세스에게 LoadLibrary() API를 호출하게 만들어 강제 삽입된 DLL의 DllMain() 함수가 실행되도록 하는 것임. LoadLibrary() API를 이용해 특정 DLL이 로딩되면 해당 DLL의 DllMain() 함수가 실행


DLL 인젝션의 활용 사례

  1. 기능 개선 및 버그 패치: 새로운 기능을 추가하거나 문제 있는 코드와 데이터를 수정할 수 있는 방식으로 사용됨
  2. 메시지 후킹: 프로세스 간의 메시지를 가로채거나 조작할 수 있음
  3. API 후킹: 삽입된 DLL이 해당 프로세스의 메모리에 대한 접근 권한을 가짐을 활용해 API 호출을 가로채고 조작
  4. 기타 응용 프로그램: 주로 PC 사용자 감시 및 관리 목적으로 개발된 애플리케이션에 활용


악성코드에서의 DLL 인젝션 활용

DLL 인젝션 기법은 악성코드에서도 활용됨. 정상적인 프로세스에 몰래 삽입되어 백도어 포트를 열어 외부에서 접근하도록 하거나, 키로깅을 통해 사용자의 개인 정보를 훔치는 등 악의적인 목적에 사용될 수 있음.

DLL 인젝션 구현 방법

  1. 원격 스레드 생성 (CreateRemoteThread() API 사용)
  2. 레지스트리 이용 (AppInit_DLLs 레지스트리 값 설정)
  3. 메시지 후킹 (SetWindowsHookEx() API 사용)

 

CreateRemoteThread()
https://github.com/reversecore/book/tree/master/%EC%8B%A4%EC%8A%B5%EC%98%88%EC%A0%9C/03_DLL_Injection/23_DLL_Injection/bin

book/실습예제/03_DLL_Injection/23_DLL_Injection/bin at master · reversecore/book

리버싱 핵심원리 - 소스 코드 및 실습 예제. Contribute to reversecore/book development by creating an account on GitHub.

github.com

여기서 myhack.dll 파일 사용했음
 
 
 
실습파일을 작업 폴더에 복사
notepad.exe프로그램 실행: 프로세스 익스플로러를 실행해 notepad.exe.프로세스의 PID를 알아냄
DebugView 실행: DebugView는 시스템에서 실행되는 프로세스들이 출력하는 모든 디버그 문자열을 가로채 보여주는 유틸리티
DLL 인젝션 확인

'

네이버 사이트의 index.html파일이 정상적으로 다운된 것을 확인 가능
 
 
 
코드 분석
 
myhack.cpp

//myhack.cpp

#include "windows.h"
#include "tchar.h"

#pragma comment(lib, "urlmon.lib")

#define DEF_URL			(L"http://www.naver.com/index.html")
#define DEF_FILE_NAME	(L"index.html")

HMODULE h_hMod = NULL;

DWORD WINAPI ThreadProc(LPVOID lParam)
{
	TCHAR szPath[_MAX_PATH] = {0,};
	
    if( !GetModuleFileName( ghMod, szPath, MAXPATH ) ) 
    	return FALSE;

	TCHAR *p = _tcsrchr( szPath, '\V ); 
    if( !p ) 
    	return FALSE;
        
	_tcscpy_s(p+l, _MAX_PATH, DEF_FILE_NAME);
    
	URLDownloadToFile(NULL, DEF_URL, szPath, 0, NULL);
    
	return 0;
}

BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID IpvReserved)
{
	HANDLE hThread = NULL;

	g_hMod = (HMODULE)hinstDLL;

	switch( fdwReason ) 
    {
	case DLL_PROCESS_ATTACH :
		OutputDebugString(L"myhack.dll Injection!!!");
		hThread = CreateThread(NULL, 0, ThreadProc, NULL, 0, NULL); 
        CloseHandle(hTh read);
		break;
	}
	
    return TRUE;
}

 
DLL이 로딩될 때 디버그 문자열을 출력하고 스레드를 실행
TreadProc()은 urlmon!URLDownloadToFile() API를 호출해 네이버 사이트의 index.html 파일을 다운받음
-> notepad.exe 프로세스에 myhack.dll이 인젝션되면 결국 URLDownloadToFile() API가 호출됨
 
 
InjectDll.cpp

// InjectDll.cpp

#include "windows.h"
#include "tchar.h"

BOOL InjectDll(DWORD dwPID, LPCTSTR szDHPath)
{
	HANDLE hProcess = NULL, hThread = NULL;
	HMODULE hMod = NULL;
	LPVOID pRemoteBuf = NULL;
	DWORD dwBufSize = (DWORD) ( tcslen(szDHPath) + 1) * sizeof (TCHAR);
	LPTHREAD_START_ROUTINE pThreadProc;
    
	// #1. dwPID를이용하여대상프로세스(notepad.exe)의 HANDLE을구한다.
	if ( ! (hProcess = OpenProcess(PROCESS_ALI__ACCESS, FALSE, dwPID)) ) 
    {
		_tprintf(L"OpenProcess(%d) failed•!! [%d]\n", dwPID, 
        	GetLastError());
		return FALSE;
	}
    
	// #2. 대상프로세스(notepad.exe) 메모리에 szDHPath 크기만큼 메모리를할당한다.
	pRemoteBuf = VirtualAllocEx(hProcess, NULL, dwBufSize, MEMCOMMIT, PAGE_READWRITE);
	
    // #3. 할당받은메모리에 myhack.dll 경로("c:\\myhack.dll")를쓴다.
	WriteProcessMemory(hProcess, pRemoteBuf, (LPVOID)szDUPath, dwBufSize, NULL);

	// #4. LoadLibraryWO API 주소를구한다.
	hMod = GetModuleHandle(L"kernel32.dll'');
	pThreadProc = (LPTHREAD_START_ROUTINE)GetProcAdd ress(hMod, "LoadLibraryW");

    // #5. notepad. exe 프로세스에스레드를 실행
	hThread = C reateRemoteTh read(hP rocess,		//hProcess
									NULL,			//IpThreadAttributes
									0,				//dwStackSize
									pThreadProc,	//IpStartAddress
									pRemoteBuf,		//IpParameter
									0,				//dwCreationFlags
									NULL);			//IpThreadld
	WaitForSingleObject(hThread, INFINITE);
	CloseHandle(hTh read);
	CloseHandle(hP rocess);

	return TRUE;
}

int _tmain(int argc, TCHAR *argv[])
{
	if( argc != 3) 
    {
		_tprintf(L"USAGE : 잉s pid dll_path\n'\ argv[0]);
		return 1; 
        }

	// inject dll
	if( InjectDll((DWORD)_tstol(argv[I]), argv[2]) )
		tprintf(L"InjectDll(\"%s\") success!!!\n", argv[2]);
	else
		_tprintf(L"InjectDll(\"%s\") failed!!!\n°, argv[2]);
	return 0; 
}

Main() :프로그램의 파라미터 체크한 수 InjectDll()함수를 호출
InjectDll() : DLL 인젝션을 해주는 핵심 함수
InjectDll()함수는 대상프로세스로 하여금 스스로 Load Library API를 호출하도록 명령하는 기능 有
 
 
디버깅 방법
DLL 파일이 인젝션되는 순간부터 디버깅을 시작하기 위해서는 인젝션 시점에서부터 프로세스를 중단하고 디버거를 연결하는 방식이 필요함. 일반적으로는 CreateRemoteThread 호출 시점, LoadLibrary 호출 시점, 혹은 DllMain 함수 진입 시점에서 브레이크포인트를 설정하여 인젝션 순간부터 DLL의 동작을 추적할 수 있음.
DLL 인젝션 방법

1. 원격 스레드 생성(CreateRemoteThread API)

CreateRemoteThread API를 사용하여 대상 프로세스에 원격 스레드를 생성하고, LoadLibrary를 호출하여 DLL을 인젝션하는 방법임. 대상 프로세스가 LoadLibrary를 호출하게 만들어 강제로 DLL을 로드하게 함
 

2. 레지스트리 이용 (AppInit_DLLs)

레지스트리를 이용한 DLL 인젝션 방법으로, Windows 운영체제에서 기본 제공하는 AppInit_DLLs와 LoadAppInit_DLLs라는 레지스트리 항목을 이용함. 인젝션하려는 DLL 경로를 AppInit_DLLs 항목에 지정하고, LoadAppInit_DLLs의 값을 1로 설정 후 시스템을 재부팅하면 모든 프로세스에 해당 DLL이 인젝션

진행 순서

  1. DLL 파일 복사
  2. 레지스트리 값 입력
  3. 재부팅

 

3. 메시지 후킹 (SetWindowsHookEx API)

SetWindowsHookEx API를 사용해 메시지 훅을 설치하면, 운영체제는 훅 절차가 포함된 DLL을 프로세스에 강제로 인젝션함. 이는 메시지 후킹을 통해 특정 이벤트에 반응하도록 구성하는 방식으로, DLL 인젝션의 한 기법
 

반응형