Windows internals 7/e
windows internals에서의 최신 프로세스(morden app) 의미
- UWP 앱 = 이머시브 프로세스(immersive process) = 윈도우 앱
- 윈도우 8 및 윈도우 서버 2012 이후부터 이용 가능한 새로운 유형의 어플리케이션
- 이전의 윈도우 프로세스는 전통적인 윈도우 프로세스/데스크톱 프로세스 라고 칭한다.
최신 프로세스를 생성하는 것은 올바른 실행 파일 경로를 CreateProcess에 전달하여 실행하는 그 이상이 필요하다.
- 특정 커맨드라인 인자
- 스토어 앱 패키지 이름으로 설정할 PROC_THREAD_ATTRIBUTE_PACKAGE_FULL_NAME키
- 해당 키를 문서화되어있지 않은 프로세스 속성인 UpdateProcThreadAttribute를 통해 추가.
윈도우 어플리케이션은 전통적 or 최신 어플리케이션을 시작.
그러나 익스큐티브는 네이트브 프로세스와 최솟 프로세스, 피코 프로세스같이 윈도우 API를 우회하여 실행되어야 하는 추가적인 프로세스를 지원함.
CreateProcess 흐름
- 윈도우 시스템은 multiple-environment 서브시스템 구조임.
- 그래서 익스큐티브 프로세스 객체와 윈도우 서브시스템 프로세스를 만드는 작업이 분리.
1. 매개변수와 플래그의 유효성 검사 및 변환
프로그램 실행 파일을 열기 전에 CreateProcessInternalW는 다음과 같은 과정을 거침.
1) CreateProcess에서 새로운 프로세스의 우선순위 클래스는 CreationFlags 인자 내 독립적인 비트로 명시.
여러가지 클래스의 플래그 지정 가능. 가장 낮은 우선순위 클래스가 선택되어진다.
- Idle(유휴)
- Below Normal
- Normal
- Above Normal
- High
- Real-time
우선순위 클래스 값은 프로세스 자체에 직접 영향을 주는 것이 아니라.. 프로세스 내의 스레드에만 영향을 준다.
2) 우선순위 클래스 지정 안된 경우 기본 값 Normal
- 스케줄링 우선순위 증가(SE_INC_BASE_PRIORITTY_NAME) 특권 없는 프로세스가 새로운 프로세스 생성 시 Real-time 우선순위 적용하려 하면 High가 대신 사용됨.
- 프로세스 생성은 REal-time 우선순위 클래스로 동작하는 프로세스를 생성 시 권한 부족하다고 실패하지는 않지만.. 새로운 프로세스는 Real-time 만큼의 우선순위 가지지 못함.
3) 플래그가 DEBUG_PROCESS 등의 경우 Kernel32는 DbgUniConnectToDbg 호출.
- Ntdll.dll 내 네이티브 디버깅 코드와의 연결 초기화 + TEB 내의 디버그 객체 핸들 획득
- 해당 실행 파일에 대한 Image File execution Options 레지스트리 키에서 Debugger 값은 건너뜀
- 안하면 무한루프 진입.
- 건너뛰지 않으면 디버거는 자신의 디버기 프로세스를 생성할 수 없다.
4) 사용자 지정 속성 목록 사용 가능. 230p의 표
→ 속성 리스트.
5) 프로세스가 잡 객체의 일부거나 플래그가 별도의 VDM(가상 DOS머신) 요청 시 Creation Flag는 무시됨.
- Job: 작업의 단위. 하나 또는 그 이상의 프로세스 커널 객체
6) CreateProcessInternalW로 전달된 애플리케이션과 커맨드라인 인자 분석.
7) 이런식으로 취합된 정보는 하나의 구조체인 RTL_USER_PROCESS_PARAMETERS로 변환됨.
2. 실행할 이미지 오픈
여기서 생성 스레드는 커널모드로 전환 —> NtCreateUserProcess 시스템 호출
1) NtCreateUserProcess 는 인자 유효성 검사
- 인자 검사 반복 이유: 커널로 전환하려는 목적으로 변조 및 악의적인 인자를 가지고 익스큐티브를 호출하는 것이 아니라는 것을 확인하기 위해
2) 실행 파일을 실행할 윈도우 이미지 찾기. 나중에 새로운 프로세스의 주소 공간으로 매핑해줄 섹션 객체를 생성할 것.
- Dos .bat 또는 .cmd —> Cmd.exe 실행
- Win16 —> NtVdm.exe 실행
- Dos .exe, .com —> NtVdm.exe 실행
- 윈도우 —> EXE 실행
여기서 섹션 객체를 생성하긴 했지만 유효한 윈도우 실행 이미지라는 것은 아니다.
3) 보호 프로세스 생성 시 서명정책 검사
4) 트러스트릿이라면 안전한 커널(Secure Kernel)이 사용할 수 있도록 특수 플래그로 섹션 객체 생성
5) Image File Execution Options 레지스트리 열어서 서비키 중 파일명과 확장자가 같은 키 값이 있는지 찾는다.
- 있다면 커널은 PspAllocateProcess를 호출하여 키 아래의 Debugger 항목의 값 확인.
- Debuger 항목 값이 존재하면 해당 값을 이미지 이름으로 바꿔서 CreaateProcessInternalW를 처음부터 시작.
HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Image File Execution Options
※ image file execution options 통한 악성코드 만들기
https://cleverdj.tistory.com/115
3. 윈도우 익스큐티브 프로세스 객체 생성
유효한 윈도우 실행 파일 오픈 + 새로운 프로세스 주소 공간에 매핑할 섹션 객체도 생성함.
이제 PspAllocateProcess 호출할 것.
→ 이미지를 실행시킬 윈도우 익스큐티브 프로세스 객체를 만든다.
✅익스큐티브 프로세스 객체 만들기✅
- EPROCESS 객체 설정
- 초기 프로세스 주소 공간 생성
- 커널 프로세스 구조체(KPROCESS) 초기화
- 프로세스 주소 공간 초기화 마무리
- PEB 설정
- 익스큐티브 프로세스 객체 설정 마무리
4. 초기 스레드와 그 스택 및 컨텍스트 생성
익스큐티브 프로세스 객체 설정이 완료되었으니.. 스레드를 생성해 줄 차례임.
초기 스레드는 커널에 의해 내부적으로 생성됨.
NtCreateThread -(호출)→ PspCreateThread 가 의존하는 보조루틴 두가지 사용.
- PspAllocateThread :익스큐티브 스레드 객체를 실제 생성하고 초기화
- PspInsertThread : 스레드 핸들의 생성과 보안 속성 생성 처리, 익스큐티브 스레드 객체를 스케줄링 가능한 스레드로 변환하기 위해 KeStartThread 호출.
- 작업이 끝나면 KeReadyThread 호출하여 스레드가 실행 준비 상태가 되도록 함. (지연된 준비 상태 진입)
💡 keStartThread는 스레드 객체의 일부인 KTHREAD 초기화를 함. 💡 - 프로세스로부터 스케줄러 설정 상속 - 이상적 노드나 프로세서 설정 - 그룹 친화성(affinity) 갱신 - 기본 및 동적 우선순위 설정 - 스레드 퀀텀 설정 - KPROCESS에 의해 관리되는 푸로세스 리스트에 해당 스레드를 삽입 |
5. 윈도우 서브시스템 특정적인 초기화 수행
익스큐티브 프로세스와 스레드 객체가 만들어진 상태임.
프로세스 초기화를 마무리 짓기 위해.. 윈도우 서브시스템 관련된 작업을 수행할 것이다.
1) 윈도우가 해당 실행 파일이 실행되게 할 것인지에 대한 여러 검사 수행
- 헤더의 image version 확인
- 해당 프로세스가 그룹 정책에 의해 차단된 자격증명인지 확인.
2) SRP(Software Restriction Policy)이 존재한다면, 새로운 프로세스에 대해 제한된 토큰(restricted token)을 생성
3) 비보호 프로세스인 경우 CreateProcessInternalW는 내부 함수를 호출하여 SxS 정보 얻음
- manifest 파일과 DLL 리디렉션 경로
- EXE가 존재하는 장치가 제거 가능한지의 여
💡 manifest file 💡 컴퓨팅에서 집합의 일부 또는 논리정연한 단위인 파일들의 그룹을 위한 메타데이터를 포함하는 파일 |
4) Csrss에 보내기 위해 수집된 정보에 기반을 두고 윈도우 서브시스템에 대한 메시지를 만든다.
- 윈도우 서브시스템 초기화 끝나면 윈도우 서브시스템으로 메세지를 전달해서
- 새로운 프로세스와 스레드를 위한 설정을 시작함.
- 전달하는 메세지에는 먼저 얻은 SxS 정보를 포함한다.
📨 윈도우 서브시스템은 메세지를 받고..
✔ CsrCreateProcess는 프로세스와 스레드를 핸들 복제. (프로세스 및 스레드 사용카운터 +1)
✔ Csrss 프로세스 구조체(CSR_PROCESS) 할당
✔ 새로운 프로세스의 예외 포트를윈도우 서브시스템의 범용 가능 포트로 설정.
→ 프로세스에 second-chance exception 발생 시 윈도우 서브시스템메세지 받을 수 있게.
#Debugger는 프로그램에서 발생하는 모든 예외를 살필 수 있는 first-chance를 가진다. 그런데 Debugger가 해당 예외를 처리하지 않고 프로그램을 계속 실행하면, 프로그램은 예외를 만나게 된다. #프로그램 단에서 예외처리코드가 없을 때 Debugger는 처리하지 않은 예외를 다시 한번 확인이 가능한데, 이를 Second-chance exception이라고 한다. |
✔ CSR_PROCESS 구조체 할당되고 초기화.
✔ CsrCreateThread가 프로세스의 스레드 리스트에 해당 스레드 추가
✔ 프로세스 종료 레벨을 0x280으로 설정(기본 프로세스 종료 레벨 값)
✔ 새로운 CSR_PROCESS 구조체를 윈도우 서브시스템의 전역적 프로세스 리스트에 추가한다.
📌 Csrss.exe이 해당 과정들을 수행한 후..
CreateProcessInternalW은 프로세스가 상승된 권한으로 수행됐는지를 검사.
- 프로세스가 설치 프로그램인지 검사하는 것을 포함함.
- 상승된 권한으로 수행되었다 ▶▶ 프로세스는 ShellExcute를 통해 실행됐고, AppInfo 서비스가 사용자에게 권한 상승 등의 대화상자를 보여준 후 권한이 상승되었다는 의미.
- 보호 프로세스는 이러한 검사 수행하지 않음.
6. 초기 스레드의 실행 시작
CREATE_SUSPENDED 플래그 지정하지 않았다면.. 초기 스레드 resume. 실행됨
그리고 새 프로세스의 컨텍스트에서 나머지 프로세스 초기화 작업을 수행한다.
7. 새 프로세스의 컨텍스트에서 프로세스 초기화 수행
새로운 스레드는 커널모드 스레드 시작 루틴인 KiStartUserThread를 실행하며 시작됨.
- KiStartUserThread: 스레드의 IRQL 레벨을 DPC/dispatch 레벨 → APC 레벨로 내린다.
- 그리고 시스템 초기 스레드 루틴인 PspUserThreadStartup 호출.
IRQL(Interrupt ReQuest Level) - DPC/Dispatch_LEVEL: IRQL 2. IRQL 3 이상의 루틴이 모두 실행된 이후 실행되는 레벨이다. - APC_LEVEL: IRQL 1. 비동기 프로시저 호출과 관련된 인터럽트 루틴. - PASSIVE_LEVEL: IRQL 0. 가장 낮은 우선순위를 가짐. 모든 인터럽트 레벨에 의해 선점당할 수 있음. 유저 코드가 실행할 수 있는 유일한 IRQL. |
📌PspUserThreadStartup 의 수행
- x86 아키텍처에 대한 예외 체인 설치
- IRQL을 PASSIVE_LEVEL로 내린다.
- 프로세스의 primary process token swap (Access Token swap) 실행 시 교환할 수 있는 기능 비활성화
- 커널 모드 데이터 구조체에 존재하는 정보에 기반을 두고 Locale ID와 이상적 프로세서를 TEB에 설정.
- DbgkCreateTrhead 호출.
- 새로운 프로세스에 대한 이미지 통지가 보내졌는지 검사
- 통지가 전달되지 않았다면, ①통지 활성화, ②새로운 프로세스에 대한 이미지 통지 전달, ③이미지 로드에 대한 통지 전달. 순서대로 수행 - 프로세스가 Debuggee인지 살펴보는 검사 수행.
- 애플리케이션 프리패칭(prefetching) 활성화 유무 검사
- 활성화 ▶ 프리패처와 슈퍼패치를 호출하여 프리패치 명령 파일 처리. 후 프리패칭 수행 - 전역 쿠키가 SharedUserData 구조체에 설정되어있는지 점검
- 없으면 생성한다.
- ※ 전역쿠키: 특정 유형의 취약점 공격을 방어하기 위해 내부적으로 포인터를 디코딩 및 인코딩하는데 사용. - 안전한 프로세스(IUM 프로세스)라면 제어를 secure kernel로 이동시키는HvlStartSecureThread를 호출하여 스레드를 실행.
- 초기 싱크(initial thunk) 컨텍스트 설정..
- 이미지 로더 초기화 루틴(Ntdll.dll의 LdrInitializeThunk), 시스템 전역적 스레드 시작 스텁(Ntdll.dll의 RtlUserThreadStart) 실행하기 위해서.
#LdrInitializeThunk: 로더와 힙 매니저, NLS 테이블, 스레드 로컬 스토리지(TLS), 파이버 로컬 스토리지(FLS) 배열, 크리티컬 섹션 구조체 초기화.
#이 후 필요한 DLL 로드하고 DLL EntryPoint(진입점)을 DLL_PROCESS_ATTACH 코드로 호출한다. 이 외의 값으로 호출 시 무시됨.
#PspUserThreadStartup 함수 복귀하면 NtContinue가 새로운 사용자 컨텍스트를 복구하고 유저모드로 복귀함. 이제 스레드가 실행.
#RtlUserThreadStart: 실제 이미지 진입점 주소와 시작 인자를 이용하여 애플리케이션의 진입점 호출.
.
.
이벤트가 이렇게 복잡한 이유❓❓
- Ntdll.dll의 이미지 로더가 내부적으로 프로세스를 설정하기 위해.
- 다른 유저 모드 콛그ㅏ 정상적으로 실행되게 하기 위해
- 모든 스레드가 공통 루틴에서 시작되게 함으로써 예외 처리를 묶어서 할 수 있음. 스레드 크래시(충돌) 시 Ntdll.dll은 이 사실을 알고서 Kernel32.dll 내 처리되지 않은 예외 필(unhandeked exceotion filter)터를 호출할 수 있다.
PSActiveProcessHead. 247p
https://www.ahnlab.com/kr/site/securityinfo/secunews/secuNewsView.do?seq=17602
first-chance exception과 second-chance exception
[Debugging] First-chance Exception과 Second-chance Exception
p.257
실습: 프로세스 시작 추적하기
실습 환경: Windows 10 Home x64 21H2
실습 대상: cmd.exe, notepad.exe
실습 도구: process Monitor v3.89
1. cmd.exe 통해 notepad.exe 실행
2. 프로세스 모니터에 해당 프로세스 이름의 필터 추가
3. 캡처(event logging) 중지된 상태에서 cmd 실행
4. 캡처 시작 후 notepad.exe 실행
CreateProcess*
프로세스가 시작되기 전의 첫 스레드 생성되었을 때..
Cmd.exe는 RegOpenKey 통해
HKLM\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Image File Execution Options\\notepad.exe 레지스트리 키를 읽는다.
이벤트의 스택을 확인함으로써 프로세스 생성의 흐름의 각 부분에 대해 자세히 알 수 있다.
- User mode? Kernel Mode?
- 어떤 루틴에서 수행? 등 …
이제 notepad.exe 프로세스에서 발생하는 이벤트 확인.
커널 모드 내의 유저 모드 스레드 시작 래퍼(Wrapper)에 의한 것임.
- 이미지 로드 통지 메시지는 Notepad.exe 프로세스 컨텍스트 내 코드에 의해서만 생성가능함.
Notepad.exe가 시스템에서 한 번이라도 실행된 적이 있다면.. 프리패치 데이터베이스는 존재함.
- 프리패처는 데이터베이스 내의 명렁을 수행
- 여러 DLL을 질의하고 읽어들이는 것을 확인할 수 있음
- 해당 행위는 보통의 DLL과 달리.. Notepad가 필요로 하는 라이브러리에 대해 이미 알고 있는 프리패처에 의해 발생된다.
※ 프리패처(Prefetcher)
- Notepad.exe를 위해 이미 만들어진 프리패치 데이터베이스 파일을 찾는다.
- 메모리 관리자의 한 요소
- 프리패칭을 통해 Windows Boot Process 속도 상승, 프로그램 실행시간을 감소시켜줌.
DLL 이미지 로딩
- 이벤트가 유저 모드 내에서 실행하는 코드에서 발생함.
- LdrInitializeThunk에 의해 호출되는 LdrpInitializeProcess로부터 발생.
Notepad의 winMain함수에서 발생하는 이벤트가 나타낼 때까지.. 나타나는 추가적인 이벤트는 해당 루틴과 보조 함수에 의해 발생하는 것이다
266p
실습: 이미지 로더 감시하기
로더 스냅(loader snaps)이라는 디버깅 기능 활성화하기 위해 전역 플래그 사용.
▶ 이를 이용하면 애플리케이션 시작과정 디버깅 시 이미지 로더에서 발생하는 디버그 출력을 확인할 수 있음.
1. gflags.exe 시작 후 image file 탭 클릭
2. Windbg 켜서 Open Excutable. —> notepad.exe
3. 디버그 정보 확인
4. 디버거는 로더 코드의 어딘가에서 멈출 것.
계속 Run하다보면 로더로부터 추가적인 메시지 + Notepad 실행.
'System > windows' 카테고리의 다른 글
cmd에서 방화벽 끄는 명령어 netsh (0) | 2022.07.19 |
---|---|
윈도우에서 putty 서버(ubuntu)로 파일 전송. PSCP.exe 사용법 (0) | 2022.07.01 |
ch3. #1 프로세스 핵심 구조체 (0) | 2022.07.01 |
Windows 이벤트 뷰어 (0) | 2022.06.17 |
윈도우 인증 과정과 LSA Protection 레지스트리 (0) | 2022.06.17 |