참고
# 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 |