tmxklab

APC Injection 본문

Security/07 Malware Technique

APC Injection

tmxk4221 2021. 4. 19. 23:46

0. 목차

 

1. APC Injection이란

  • Remote DLL Injection과 유사하지만, CreateRemoteThread()를 사용하는 대신 비동기 프로시저 호출(APC, Asynchronous Procedure Calls)을 사용해 타겟 프로세스의 스레드가 악성 DLL을 로드하도록 한다.

 

비동기 프로시저 호출 (APC)

  • APC함수는 일반적으로 사용하는 parameter를 전달받아 바로 호출하는 SPC(Synchronous Procedure Calls)함수와 달리 특정 스레드의 콘텍스트에서 비동기적으로 실행되는 함수이다.
  • 각 스레드는 타겟 스레드가 알람 가능한 상태(Alertable State)가 될 때 실행되는 APC Queue를 포함하며 QueueUserAPC()를 통해 유저 정의 코드를 해당 스레드의 APC Queue에 넣는다.
  • APC Queue
    • 쓰레드가 알람 가능한 상태(Alertable State)가 되었을 때 호출할 콜백 함수들을 모아둔 Queue이다.

 

Alertable State란?

스레드에는 생성되어 없어질 때까지 다음과 같이 자신의 상태를 가지고 있다.

  • Waiting
    • thread가 특정 event를 받기 이전까지 아무것도 하지 않는 상태
    • CPU scheduling 대상에서 해당 thread는 제외된다.
  • Ready
    • CPU scheduling 대상이긴 하나 아직 CPU time을 받지 못한 상태
    • 이 경우 CPU time만 받으면 바로 실행 상태(Running)로 변경된다.
  • Running
    • CPU가 현재 이 thread를 수행하고 있는 상태

 

위 3가지의 상태 외에 다른 상태가 존재하는 데 바로 Alertable State이다.

만약 Waiting 상태에서 event를 기다리는 thread는 특정 event가 발생하면 Ready 상태로 변경해주고 Scheduler에 의해 CPU Time을 받게 되면 Running상태로 진입하게 된다.

하지만, Alertable State는 사용자가 조정할 수 있는 유일한 thread의 상태로 다른 작업을 진행하다가 특정 작업이 완료되면 다른 작업들을 제처두고 완료된 작업을 처리하는 함수(CR, Completion Routine)의 우선순위를 높여줄 수 있는 상태이다. 이를 통해 사용자가 유연하게 소프트웨어를 디자인할 수 있게 도와준다.

(즉, Alertable State가 되어야 CR함수가 실행될 수 있다.)

 

앞서 말한 APC Queue에 있는 함수는 쓰레드가 Alertable State가 되면 큐에 있는 함수들이 호출된다.

 

다음 함수는 Thread의 상태를 Alertable State로 변경할 수 있는 함수들이다.

SleepEx() 
SignalObjectAndWait() 
MsgWaitForMultipleObjectsEx() 
WaitForMultipleObjectsEx() 
WaitForSingleObjectEx()

 

Thread가 Alertable 상태로 진입하게 되면 APC Queue에 Queueing된 정보가 있는지 확인을 하게 된다. (Queueing된 정보란 QueueUserAPC()에 의해서 전달된 정보를 만한다.)

 

QueueUserAPC

pfnAPC

  • APC procedure의 function pointer

 

hThread

  • 스레드에 대한 핸들 값이며 핸들에는 THREAD_SET_CONTEXT 액세스 권한이 있어야 한다.
  • 사용자가 정의한 APC procedure를 어떤 thread가 호출할 것인지

 

dwData

  • pfnAPC가 가리키는 function에 넘겨주는 parameter 값

 

 

 

앞서 말한 내용들을 정리해보자

(참고로, 모든 스레드들은 자신만의 APC Queue를 가진다.)

QueueUserAPC()를 통해서 특정 함수를 APC Queue에 넣는다.

② 다른 로직들을 처리한다.

③ Thread를 알람 가능한 상태(Alertable State)로 만들어 준다.

APC Queue에 있던 함수들이 다 호출된다.

 

2. 동작 과정

APC Injection 기술이 동작하는 방법은 악성코드 프로세스가 알람 가능한 상태에 있거나 알람 가능한 상태로 전환될 것 같은 타겟 프로세스의 스레드를 식별한다. 그러면 유저 정의 코드를 타겟 스레드의 APC QueueQueueUserAPC()를 통해 저장한다. 만일, 타겟 스레드가 알람 가능한 상태에 들어가면 유저 정의 코드가 APC Queue에서 선택되어 타겟 프로세스의 스레드에 의해 실행될 것이다.

 

① OpenProcess()를 통해 타겟 프로세스의 핸들을 구한다.

② VirtualAllocEx()를 통해 타겟 프로세스의 공간을 할당받는다.(인젝션할 위치)

③ WriteProcessMemory()를 통해 데이터를 작성한다.(쉘 코드, dll 등...)

④ OpenThread()를 통해 타겟 프로세스읲 스레드 핸들을 구한다.

⑤ QueueUserAPC()를 통해 타겟 스레드에 실행할 APC 함수를 큐잉한다.

 

이후에, 스레드가 알람 가능한 상태로 들어가면 스레드는 APC 큐에서 APC함수가 실행될 것이다.

 

3. APC DLL Injection 디버깅

다음 코드를 컴파일하여 디버깅 해보자

bcmmeijer/APCInjection
Inject DLL in target process using APC calls. Contribute to bcmmeijer/APCInjection development by creating an account on GitHub.
https://github.com/bcmmeijer/APCInjection

 

추가로 인젝션할 dll도 만들어 주자

msg.dll - 인젝션되는 DLL

#include <Windows.h>  
void main() {     
	MessageBoxA(NULL, "Hello!", "Pwned", NULL); 
}  
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) {     
	switch (ul_reason_for_call){     
		case DLL_PROCESS_ATTACH:         
			main();         
			break;     
		case DLL_THREAD_ATTACH:         
			break;     
		case DLL_THREAD_DETACH:         
			break;     
		case DLL_PROCESS_DETACH:         
			break;     
	}     
	return TRUE; 
}
  • 타겟 프로세스에 해당 dll이 로드되면 메시지 박스를 띄우는 코드이다.

 

  • 코드 흐름은 간단하게 3부분으로 나뉜다.
  • 먼저 FindProcess()를 이용하여(사용자 정의 함수임) 타겟 프로세스를 찾고 OpenProcess()를 통해 핸들 값을 가져온다.
  • 그 다음 인젝션할 dll path값이 들어있는 buffer를 VirtualAllocEx()WriteProcessMemory()의 파라미터로 줘서 타겟 프로세스에 dll path값을 저장한다.
  • 마지막으로 GetProcAddress()를 통해 얻을 수 있는 kernel32.dll에 있는 LoadLibraryW()의 주소 값과 OpenThread()를 통해 얻을 수 있는 타겟 프로세스의 핸들 값을 QueueUserAPC()의 파라미터로 넘겨준다.
  • 이를 통해 타겟 스레드의 APC QueueLoadLibraryW()와 파라미터인 dll path값이 전달되었으며 타겟 스레드의 상태가 Alertable 상태로 변하는 즉시, dll이 로드되어 dllMain에 있는 메시지 박스가 호출될 것이다.

 

다음은 디버깅 화면을 통해 동작 과정을 살펴보자

  • APCInjector.exe프로세스에서 타겟 프로세스인 sublime_text.exe에 메모리 할당 후 WriteProcessMemoy()를 통해 할당받은 영역에 msg.dll path값을 쓴다.
  • sublime_text.exe프로세스에서 아까 할당받은 영역을 확인해보면 값이 잘 들어간 것을 확인
  • 이제 타겟 프로세스의 스레드 핸들 값을 가져온다. → 0xB0
  • ProcessExplorer를 통해 확인
  • QueueUserAPC()를 호출하기 전에 파라미터 값을 세팅해준다.
  • 파라미터에는 앞서 1. GetProcAddress()를 통해 구한 LoadLibraryW()의 주소 값2. 타겟 프로세스의 스레드 핸들 값, 3. 마지막으로 아까 타겟 프로세스에 작성한 msg.dll path값이 위치한 주소를 준다.
  • 실행시켜주면 타겟 스레드의 APC QueueLoadLibraryW("msg.dll path")가 들어가고 로드되었는지 바로 MessageBox가 뜬다.
  • 실제로 sublime_text.exe에는 msg.dll이 로드된 것을 확인할 수 있다.

 

위에서는 QueueUserAPC()를 실행시키자마자 바로 뜬 것을 통해 sublime_text.exe의 타겟 스레드가 Alertable State로 전환하는 로직이 있거나 아니면 타겟 스레드가 Alertable State인 상황인 것 같다.

 

다시 한 번 APCInjector를 실행시켜서 확인을 해보자.

  • QueueUserAPC()에게 전달하는 타겟 스레드 핸들 값 : 0x98
  • 타겟 스레드 ID : 15580
  • sublime_text.exe의 스레드 중에 TID값이 15580인 스레드를 확인해보면 UserRequest상태이다.

 

UserRequest상태가 무엇인지 몰라서 찾아보니...

Thread wait reasons
I've been using code that I found in the following post: How to get thread state (e.g.
https://stackoverflow.com/questions/48009277/thread-wait-reasons

두둥...

 

앞서 설명한 스레드가 Alertable State로 전환할 수 있게 도와주는 함수(WaitForSingleObjectEx, WaitForMultipleObjectsEx, ...)를 사용하여 타겟 스레드가 Alertable State인 상황인 것을 알 수 있다.

 

끗.

 

4. 참고자료

19장. Alertable State, APC
유투브 강의에 대한 정리다. 19장. 알림가능한 상태 Alertable State 일반적인 Sleep함수인데, 두번째 전달인자를 TRUE로 하면 => 이 함수를 호출한 쓰레드는 Alertable State가 된다. *프로세스 아니고 쓰레드 예를들어 A I/O를 요청했다. 그리고 연결된 부가작업(CompletionRoutine함수)있다. 이 때 기존에 하고있던 일, CR함수에 우선순위가 있다. *이런 제어가 가능해야 우리가 소프트웨어를 안정적으로 디자인할 수 있다.
https://awesome-dev.tistory.com/89
APC에 대하여
정말 간만에 vc newsgroup에 돌아왔습니다. APC 는 asynchronous procedure call 의 약자입니다. 그렇다면 synchronous procedure call(이하 SPC 라고 합시다)는 무엇일까요? SPC는 일반적으로 우리하 호출하는 함수입니다. 즉 함수의 이름과 parameter를 전달하면 stack을 이용하여 parameter를 push하고 instruction pointer를 호출한 함수로 이동하게 되겠지요. 뭐 일반적인 함수의 호출방식이니 이에 대한 문의는 없을 것 같구용.
http://egloos.zum.com/himskim/v/1053865
Ten process injection techniques: A technical survey of common and trending process injection techniques
Process injection is a widespread defense evasion technique employed often within malware and fileless adversary tradecraft, and entails running custom code within the address space of another process. Process injection improves stealth, and some techniques also achieve persistence.
https://www.elastic.co/kr/blog/ten-process-injection-techniques-technical-survey-common-and-trending-process
#024_Window_Network_비동기 소켓 입출력 모델_Overlapped 모델 (2)
안녕하세요 삽잡이입니다. 이번 시간에는 완료 루틴(Completion Routine)을 사용하는 Overlapped 모델에 대해서 알아보고자 합니다. 이번 모델은 비동기 방식을 사용하는 I/O 작업을 전문 쓰레드에 맡깁니다. 이처럼 I/O 작업만을 전문적으로 받는 쓰레드가 여러대 있다고 한다면, 이전 모델들은 A, B 클라이언트들에서 데이터가 들어오면 A 클라이언트의 작업을 처리하고, B 클라이언트의 작업을 처리해줘야했었는데, 이 모델은 I/O 작업을 전문적으로 받는 쓰레드를 사용하기 때문에 A, B 각각 동작하도록 한다 이겁니다...
https://blog.shovelman.dev/529

'Security > 07 Malware Technique' 카테고리의 다른 글

다양한 인젝션 기술  (0) 2021.04.20
SetWindowsHookEx DLL Injection  (0) 2021.04.20
악성코드 기능  (0) 2021.04.18
악성코드 지속메커니즘  (0) 2021.04.18
파일리스(Fileless)기법 설명  (0) 2021.01.16
Comments