본문 바로가기

System/windows

APC (Asynchronous procedure call)

참고
# Windows 시스템 프로그래밍 제 3판 JOHNSON M. HART 저
# Micosoft 설명서 (링크)

 

 

APC (Asynchronous procedure call)

1. 개념 

- 인자를 전달받아 바로 호출하는 SPC(Synchronous Procedure Calls) 함수와 달리, APC 는 특정 스레드의 컨텍스트에서 실행되기 위해 queue 에 삽입되는 비동기적으로 실행되는 함수임

- 정규 실행 경로를 실행하기 전에 스레드가 다른 코드를 실행하도록 하는 것이 가능

- 모든 스레드는 스레드에 첨부된 APC queue 를 가짐.

- 시스템 전체에 걸쳐 있는 DPC queue 와는 달리 APC queue 는 스레드 별로 독립적으로 존재한다.

 

① 스레드가 alertable wait 상태일 때 애플리케이션이 Queue 에 APC 를 쌓음

② APC(UserMode)가 대기중일 때 커널은 스레드를 중단하고(alert) APC 루틴에게로 컨트롤을 넘김

③ 스레드는 자신의 APC queue 에 있는 모든 APC 에 대해 하나씩 APC 함수를 호출

④ APC 루틴이 완료됐을 때 커널은 스레드를 다시 실행

 

[요약]

 APC queue 에는 비동기적으로 호출되어야 할 함수들과 매개변수 정보가 저장된다. 그러나 저장 후 바로 호출하는 것이 아니라 스레드가 alertable wait 상태일 때 호출되는 것. 

✔ 공격자는 alertable wait 상태에 있는 스레드를 선점하여 APC 를 사용해 자신의 코드가 즉각 실행되도록 할 수 있다. 

 

 

2. 이벤트 수행 과정 - 예시​

감독 스레드가 대상 스레드를 제어한다고 가정했을 때 APC 가 사용되는 과정은 다음과 같다. 

 

⑴ 감독 스레드는 APC 루틴을 대상 스레드에 큐잉. APC 루틴을 대상 스레드에게 배정하는 것. 한 스레드에 여러 개의 APC 루틴 등록이 가능.

⑵ 대상 스레드는 alertable wait 상태로 진입. 

// 앞선 두 단계의 순서는 중요하지 않음. Race condition이 발생하지 않기 때문.

⑶ alertable wait 상태로 진입한 스레드는 등록된 모든 APC 를 수행함.

⑷ 하나의 APC 는 자원 해제 또는 예외 발생 등이 필요할 때 어떤 행동을 취할 수 있음.

이 덕분에 감독 스레드는 대상 스레드 안에서 예외가 발생하게 할 수 있다. 단, 그런 예외는 대상 스레드가 alertable wait 상태로 진입한 후에만 발생

 

감독 스레드가 언제라도 APC 를 대상 스레드에게 지정할 수 있기 때문에 APC 의 수행은 비동기적이다.

그러나 대상 스레드가 alertable wait 상태에 진입했을 때에만 APC 가 수행된다는 점에서 동기적이라고도 할 수 있다.

 

각 스레드(감독)는 QueueUserAPC()를 통해 하나의 APC 를 대상 스레드에 등록할 수 있다. 대상 스레드가 alertable wait 상태가 될 때 실행될 APC 와 사용자 정의 코드를 대상 스레드의 APC Queue 에 넣는다. 

 

DWORD QueueUserAPC (
 PAPCFUNC pfnAPC, //대상 스레드가 호출할 실제 APC 함수를 가리키는 포인터
 HANDLE hThread, //대상 스레드의 핸들
 DWORD dwDate //APC 함수가 수행될 때 함수로 전달될 인수
);

// Return value: 0이면 실패, 그 외는 성공

 

 

 

3. APC 의 유형

유저 모드 APC와 커널 모드 APC

 

모드 설명
유저 모드
APC
- 애플리케이션을 위해 생성된 APC 
- 유저모드에서 엄격하게 실행. IRQL = PASSIVE_LEVEL 
- 타겟 스레드의 컨텍스트에서 실행될 때 해당 스레드의 권한을 요구 
- 스레드가 alertable wait 상태인 경우에만 실행 가능 
- 중복 I/O 처리, ReaedFileEx(), WriteFileEx(), QueueUserAPC() 등의 Windows API 는 유저모드 APC 를 사용 
커널 모드
APC
- 시스템이나 드라이버를 위해 생성된 APC 
- 타겟 스레드의 컨텍스트에서 실행될 때 해당 스레드의 권한을 요구하지 않는다. 
- 스레드를 중단시킨 후 스레드의 개입이나 동의없이 프로시저를 실행 
- Normal Kernel Mode APC 와 Special Kernel Mode APC 가 존재

 

커널 모드 APC 종류

Normal kernel Mode
APC
- IRQL = PASSIVE_LEVEL 커널 모드에서 실행
- 유저 모드 APC 를 포함한 모든 유저 모드 코드를 선점
- 일반적으로 파일 시스템 및 FileSystemFilter Driver 에서 사용된다.
Special Kernel Mode
APC
- IRQL= APC_LEVEL 커널 모드에서 실행
- User Mode APC 와 Normal kernel Mode APC 를 포함
- ASSIVE_LEVEL 에서 실행되는 User Mode 및 Kernel Mode Code 를 선점
- OS 는 Special Kernel APC 를 이용하여 I/O request completion 를 처리한다.

 

 

4. 알림 가능한 대기 상태 

= 통지 가능한 상태 = 경고 가능한 상태 

Alertable Wait State 란 스레드의 대기(wait)상태 중 하나로, 비동기 I/O 를 위한 특별한 상태이다. 

비동기 I/O 를 함수를 호출한 스레드가 해당 상태이어야만이 완료 루틴이 수행된다.

 

ㅇ 일반적인 대기(wait) 상태 

Sleep()을 이용하여 대기가 시작되는 시점부터 끝날 때까지 CPU 시간을 사용하지 않는다. 

 

ㅇ 알림 가능한 대기(wait) 상태

알림 가능한 대기 상태 동안 CPU 시간을 할당받아 완료 루틴을 수행하고, 더 처리할 내용이 없으면 대기 상태가 종료된다.

 

APC 는 WaitForSingleObjectEx(), WaitForMultipleObjectsEx(), SleepEx() 같은 함수를 호출하여 알림 가능한 대기 상태로 전환될 수 있다. 

해당 함수들은 스레드가 큐잉된 APC 를 처리할 수 있는 기회를 제공한다. 

DWORD SleepEx(
    DWORD dwMilliseconds, // 타임 아웃 시간(대기시간)
    BOOL bAlertable // 알림 가능한 상태인지 여부(True 시 가능, False 의 경우 Sleep()과 같은 기능)
);
DWORD WaitForSingleObjectEx(
    HANDLE hHandle, // 오브젝트에 대한 핸들
    DWORD dwMilliseconds, // 타임 아웃 시간
    BOOL bAlertable // 알림 가능한 상태인지 여부(True 시 가능)
);
DWORD WaitForMultipleObjectsEx(
    DWORD nCount, // lpHandles 배열에 저장된 핸들 개수
    const HANDLE * lpHandles, // 핸들을 저장하고 있는 배열의 주소를 가리키는 포인터
    BOOL bWaitAll,
    // TRUE: lpHandles 의 모든 오브젝트가 신호를 받았을 때 함수를 반환
    // FALSE: 하나의 오브젝트만 신호를 받아도 함수 반환. 이 경우 반환 값은 신호를 준 오브젝트임
    DWORD dwMilliseconds, // 타임 아웃 시간
    BOOL bAlertable // 알림 가능한 상태인지 여부(True 시 가능)
);

 

이 외에도 Alertable Wait State로 전환할 수 있는 함수로 SignalObjectAndWait(), MsgWaitForMultipleObjectsEx()가 존재한다.

 

[요약]

비동기 I/O 작업을 위해서는 알림 가능한 대기 상태가 되어야 함.

 해당 상태가 되기 위해서는 해당 함수들의 bAlertable 플래그를 TRUE 로 설정.

 이런 식으로 완료 루틴을 제어할 수 있다.

 


[TIP] WaitForSingleObject(), WaitForMultipleObject() 함수와 Ex 가 붙은 함수의 차이

ㅇ WaitForSingleObject(), WaitForMultipleObject() 

이 함수들은 커널 오브젝트(들)이 신호를 받을 때까지 기다리는 기능을 한다.

 

WaitForSingleObjectEx(), WaitForMultipleObjectEx()

기능이 확장되어, Alertable state 인자 값을 줄 수 있는 파라미터가 추가로 존재한다.


“기존 기능 + 신호 도착 시 알림을 받을 수 있는 상태로 만들어주는 기능”

'System > windows' 카테고리의 다른 글

Obfuscating Function Call  (0) 2023.03.29
PE 파일  (0) 2022.11.21
나의 Public IP 찾기 TIP (curl)  (1) 2022.10.05
windows 관리자권한 가진 계정 생성  (0) 2022.07.19
cmd에서 권한 변경하는 명령어 runas  (0) 2022.07.19