티스토리 뷰

728x90
반응형

[Reversing] DLL Injection


- 샘플 파일 다운로드

첨부파일


Dll 인젝션은 대상 프로세스가 스스로 LoadLibrary() 함수를 호출하게 만들어서 원하는 DLL을 로드하게 하는 것으로 먼저 LoadLibrary()는 GetModuleHandle()을 이용하여 kernel32.dll을 넣어 핸들을 구하고 GetProcAddress()을 이용하여 얻은 핸들과 "LoadLibrary" 문자열을 넣어서 함수 주소를 찾는다

이후 CreateRemoteThread() 함수를 이용하여 원래 목표인 스레드를 생성하는 것이 아니고 LoadLibrary() 함수를 실행시켜 함수의 인자에 인젝션을 원하는 dll 파일의 경로를 적어 로드하는 것이다..  


  1. CreateRemoteThread() API을 이용한 인젝션 

DLL 인젝션을 하기위해서는 CreateRemoteThread()을 이용하여 스레드를 생성하는 것이 아니라 LoadLibraryA()을 호출해야 된다. 즉, LoadLibraryA()을 실행 시켜 CreateRemoteTh 

read()의 인자에 인젝션 할 DLL의 경로를 적어 프로세스가 스스로 LoadLibrary()을 호출하는 것이다. 

이러한 방법이 가능한 이유를 살펴보면 먼저 CreateRemoteThread()의 인자 중 (LPTHREAD_START_ROUTINE)llBaseAddress는 llBaseAddress가 가르키는 함수 호출 시 전달할 인자를 지정하는데 그게 ThreadProc란 콜백 함수이다. 그런데 ThreadProc, LoadLibrary는 함수 원형이 같아 return과 전달 인자를 4bte씩 받게 되어 해당 방법이 가능한 걸 확인 할 수 있다. 


 //option 1: CreateRemoteThread 

case 1: 

{ 

hThread = CreateRemoteThread(hProcessNULL0, (LPTHREAD_START_ROUTINE)llBaseAddresslpBaseAddress0, (LPDWORD)(&ThreadId)); 

if (hThread == NULL) 

{ 

ErrorExit(TEXT("CreateRemoteThread")); 

} 

break; 

} 


  1. NtCreateThreadEx(), RtlCreateUserThread() API을 이용한 인젝션 

먼저 NtCreateThreadEx()는 CreateRemoteThread() 함수의 내부에서 최종적으로 호출하는 함수이다.  

(CreateRemoteThread() → CreateRemoteThreadEx() → NtCreateThreadEx()) 

Windows OS 버전에 따라 사용하는 API가 달라지는데 Windows7 이후로 CreateRemote

Thread() API을 이용한 인젝션에 제한이 생기면서 ntdll.dll에 있는 NtCreateThreadEx() API을 사용하게 되었다고 한다. 확인 시 Windows OS 버전(Windows 10)에 따라 NtCreateTh 

readEx() 사용이 안되는 것을 확인 하였다. 때문에 RtlCreateUserThread()을 사용을 권장한다.  

(RtlCreateUserThread() → NtCreateThreadEx())


 //option 2: NtCreateThreadEx 

case 2: 

{ 

prototype_NtCreateThreadEx pfnNtCreateThreadEx = NULL; 

PVOID pvEncodedPtr = NULL; 

GetFunctionAddressFromDll("ntdll.dll""NtCreateThreadEx", (PVOID *)&pfnNtCreateThreadEx); 

pfnNtCreateThreadEx(&hThread, GENERIC_ALL, NULLhProcess, (LPTHREAD_START_ROUTINE)llBaseAddresslpBaseAddress, FALSE, NULLNULLNULLNULL); 

if (hThread == NULL) 

{ 

ErrorExit(TEXT("NtCreateThreadEx")); 

} 

break; 

} 

//option 3: RtlCreateUserThread 

case 3: 

{ 

prototype_RtlCreateUserThread pfnRtlCreateUserThread = NULL; 

PVOID pvEncodedPtr = NULL; 

GetFunctionAddressFromDll("ntdll.dll""RtlCreateUserThread", (PVOID *)&pfnRtlCreateUserThread); 

pfnRtlCreateUserThread(hProcessNULL0000llBaseAddresslpBaseAddress&hThreadNULL); 

if (hThread == NULL) 

{ 

ErrorExit(TEXT("RtlCreateUserThread")); 

} 

break; 

} 


  1. DLL Injection 정리 

마지막으로는 Msg_box(DLL) 소스코드와 DLL Injection 실행 화면 & 단계에 대해 기술하였다. 

 // Msg_box.cpp(DLL 소스코드) 

#include "stdafx.h" 

BOOL APIENTRY Msg_box( HMODULE hModule, 

                       DWORD  ul_reason_for_call, 

                       LPVOID lpReserved 

 ) 

{ 

switch (ul_reason_for_call) 

{ 

    case DLL_PROCESS_ATTACH: { 

        MessageBox(nullptrL"injection success"L"dll injection", MB_OK); 

    } 

case DLL_THREAD_ATTACH: 

case DLL_THREAD_DETACH: 

case DLL_PROCESS_DETACH: 

break; 

} 

return TRUE; 

} 


대상 프로세스의 핸들을 얻은 뒤 버퍼를 할당을 한다. 이후 인젝션 할 데이터를 삽입한 후 상황에 따른 API를 이용하여 인젝션이 진행되는 것을 확인 할 수 있다. 


OpenProcess() 대상 프로세스 핸들 Get

VirtualAllocEx() 대상 프로세스 버퍼 할당

WriteProcessMemory() 데이터 삽입

Kernel32.dll 핸들 Get

Ntdll.dll 핸들 Get

GetProcAddress() → LoadLibrary() Address Get

Windos OS Version 따라 API 결정

CreateRemoteThread()

실행 & DLL 로드

NtCreateThreadEx()/

RtlCreateUserThread()

실행 & DLL 로드

 1 – DLL Injection 단계


각 옵션에 따라 성공 유무를 확인 할 수 있었으며, Windows OS Version에 따라 (그림 1)와 같은 성공 문구와 Msg_box.dll이 추가되는 걸 확인 할 수 있었다 

 

그림 1 – DLL Injection 실행 화면 



728x90
반응형

'Reversing > Reversing Tech' 카테고리의 다른 글

[Reversing] Wscript & VBA Tip  (0) 2020.04.07
[Reversing] ZwContinue  (0) 2020.02.05
[Reversing] Ollydbg BreakPoint  (0) 2020.01.03
[Reversing] APC Injection_QueueUserAPC()  (0) 2019.12.06
[Reversing] Self Creation, 디버깅  (0) 2019.12.02
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
250x250