DLL injection

agnusdei·2025년 9월 9일

CTF

목록 보기
101/185

DLL injection(Dynamic Link Library, 동적 연결 라이브러리) — 원리부터 동작까지 (상세 설명)

먼저 중요한 점 — 본 설명은 학습·방어·포렌식 목적의 기술적·이론적 해설입니다. 실제 악용은 불법이며, 실습은 격리된 랩 환경(예: 오프라인 VM)에서만 하세요.


1) 핵심 개념 요약

  • DLL 인젝션(Dynamic Link Library Injection, 동적 연결 라이브러리 주입) 은 한 프로세스가 실행 중인 다른 프로세스의 주소 공간에 코드(일반적으로 DLL)를 로드시켜 그 프로세스의 흐름을 변경·확장하는 기법입니다.
  • 목적: 권한 획득, API 후킹(응용 프로그램 프로그래밍 인터페이스, Application Programming Interface)·모니터링, 은닉 실행(파일리스), 또는 악성 활동 은닉 등.

2) 전제 지식 — 프로세스/메모리/PE(Portable Executable, 포터블 실행 파일) 구조

정확한 동작을 이해하려면 다음 개념을 숙지해야 합니다.

  • 프로세스 주소 공간: 코드 섹션(.text), 데이터(.data), 힙(Heap), 스택(Stack), 그리고 로드된 모듈들의 메모리 매핑.
  • 모듈(Loaded module): 운영 체제(Operating System, OS) 커널이 PE(Portable Executable, 포터블 실행 파일)를 메모리에 매핑해 DLL이나 EXE로 동작.
  • IAT(Import Address Table, 가져오기 주소 테이블): 모듈이 사용하는 외부 함수들의 실제 주소가 런타임에 저장되는 테이블.
  • Relocation(재배치): ASLR(Address Space Layout Randomization, 주소 공간 레이아웃 무작위화) 등으로 기본 로드 주소가 변경될 때 PE 내의 상대 주소(RVA, Relative Virtual Address, 상대 가상 주소)를 수정하는 과정.
  • DLL 진입점(DllMain): DLL이 로드/언로드될 때 호출되는 함수(일부 기법은 이를 우회하거나 수동 호출).

3) Windows 로더(일반적인 동작) — 요약

  1. 커널이 파일(예: exe)을 메모리에 매핑(map)한다.
  2. 섹션(.text, .rdata, .data 등)을 할당된 가상 주소에 복사/매핑.
  3. 필요한 다른 DLL들을 로드(LoadLibrary 계열 호출)하고 IAT를 채움.
  4. Relocation이 필요하면 수행.
  5. 시작점(entrypoint, EXE는 main/CRT init, DLL은 DllMain)을 호출하고 스레드를 실행.

이 동작의 어느 지점에 개입하느냐에 따라 인젝션 방식과 탐지 지표가 달라집니다.


4) 대표적인 인젝션 기법들 — 원리와 동작 단계(개념적)

아래는 기법별 개념 흐름과 탐지·방어 관점에서의 특징입니다. (실행 코드 제공은 하지 않습니다 — 설명은 방어/이해용입니다.)

A. 원격 스레드 + LoadLibrary 방식 (Remote Thread + LoadLibrary)

  • 아이디어: 대상 프로세스에 DLL 경로 문자열을 쓰고, 그 주소를 인자로 해서 대상 프로세스에서 LoadLibrary를 호출하는 스레드를 만든다.

  • 개념적 단계:

    1. 대상 프로세스의 핸들(권한 필요)을 얻음.
    2. 대상 프로세스 주소 공간에 메모리 할당.
    3. 할당한 메모리에 DLL 경로 문자열을 기록.
    4. 대상 프로세스에서 LoadLibrary(또는 유사 함수)를 호출하도록 원격 스레드 생성.
  • 탐지/증거:

    • 원격 스레드 생성 이벤트(CreateRemoteThread 등)
    • 프로세스 메모리에 파일 경로 문자열이 존재
    • 대상 프로세스의 모듈 목록에 새 모듈이 로드됨(파일 기반)
  • 난이도/스텔스: 구현 쉬움, 비교적 쉽게 탐지됨.

B. SetWindowsHookEx 기반 훅 방식

  • 아이디어: Windows 훅 메커니즘을 이용해 시스템 레벨로 DLL을 로드(예: WH_CBT, WH_MOUSE 등). GUI 프로세스로 DLL이 로드됨.
  • 특징: GUI 프로세스(특히 동일 데스크탑 세션)에 대해 효과적. 레지스트리/서비스 기반이 아니어서 특정 상황에서 유용.
  • 탐지: 훅 목록, 레지스트리 설정, 프로세스 모듈 변화 등으로 탐지 가능.

C. APC(Asynchronous Procedure Call, 비동기 프로시저 호출) 주입

  • 아이디어: 대상 스레드가 유휴 상태일 때 호출될 APC를 큐에 넣어 특정 함수를 실행하게 함. QueueUserAPC 계열로 구현.
  • 특징: 원격 스레드 생성에 비해 흔적이 작을 수 있으나 대상 스레드가 유휴/알맞은 상태여야 실행됨.
  • 탐지: 스레드의 시작 주소가 예상 범위를 벗어남, 비정상적인 APC 큐 사용 패턴.

D. 스레드 하이재킹(Thread Hijacking) / 컨텍스트 변조

  • 아이디어: 대상 프로세스의 기존 스레드를 일시중단(Suspend), 레지스터 컨텍스트를 조작해서 제어를 자기 코드로 넘긴 뒤 다시 복구.
  • 특징: 원격 스레드보다 더 은밀할 수 있음(스레드 생성 흔적 없음). 다만 대상 스레드 중단과 복구 흔적 존재.
  • 탐지: 스레드 일시중단/재개 패턴, 스레드 시작 주소 변경.

E. 프로세스 할로잉(Process Hollowing) / RunPE

  • 아이디어: 합법적 프로세스를 생성(종종 Suspended 상태), 원래 매핑된 이미지의 메모리를 제거한 뒤 다른 PE 이미지를 그 자리에 매핑해 실행.
  • 특징: 파일 없는 악성 실행(파일리스)과 함께 사용됨. 탐지 회피 목적.
  • 탐지: 실행 중인 프로세스의 이미지와 디스크 상의 파일 불일치, 프로세스 시작 시 원래 이미지와 다른 섹션 레이아웃.

F. AppInit_DLLs / 레지스트리 기반 자동 로드

  • 아이디어: Windows 레지스트리(예: HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows\AppInit_DLLs)에 DLL 경로를 넣어 특정 범위의 프로세스에 자동 로드.
  • 특징: 오래된 기법(Windows 버전에 따라 제한/보안 설정으로 무력화됨). 시스템 전역적 영향.
  • 탐지: 해당 레지스트리 값 존재 여부.

G. Manual Mapping / Reflective DLL Injection (수동 매핑 / 리플렉티브)

  • 아이디어: 운영체제의 표준 로더(LoadLibrary)를 사용하지 않고, 공격자 코드가 직접 DLL(PE 파일)을 대상 프로세스 메모리에 매핑하고 런타임 초기화(Import resolution, Relocation 등)를 수행한다.

  • 핵심 단계(개념):

    1. DLL(PE) 파일의 헤더(DOS/NT 헤더)를 파싱.
    2. 각 섹션을 대상 프로세스 메모리의 적절한 주소에 복사.
    3. Relocation 테이블을 적용(기본 로드주소가 달라졌을 때).
    4. Import Table 을 수동으로 해결(다른 모듈의 Export 테이블을 스캔해서 함수 주소를 채움).
    5. TLS(쓰레드 로컬 저장소) 콜백 및 DLL 엔트리 포인트(DllMain) 호출.
  • 장점/단점:

    • 장점: 디스크에 DLL 흔적을 남기지 않을 수 있고, 표준 API 호출 흔적을 줄임(탐지 회피).
    • 단점: 구현 복잡(PE 포맷 심층 이해 필요). EDR(Endpoint Detection and Response, 엔드포인트 탐지 및 대응)에서 비정상 메모리 패턴으로 탐지될 수 있음.
  • 탐지: 메모리에 매핑된 모듈이 파일시스템에 존재하지 않음, 비정상적인 메모리 구조, IAT가 정상적으로 채워지지 않음 등.

H. 커널 모드 인젝션 / 드라이버 기반

  • 아이디어: 커널 드라이버를 통해 프로세스 주소 공간을 조작하거나 스레드/모듈 로딩을 유도.
  • 특징: 강력하나 드라이버 로드(서명 등) 제약과 탐지 위험이 있음. 드라이버 서명 정책으로 제한.
  • 탐지: 비정상 드라이버 로드, 커널 콜을 통한 프로세스 구조 조작 징후.

5) Manual Mapping(수동 매핑)의 내부(더 깊게)

Manual Mapping은 가장 기술적으로 풍부한 주제라 자세히 다룹니다(개념 수준).

  • PE 헤더 파싱: IMAGE_DOS_HEADER → IMAGE_NT_HEADERS → IMAGE_SECTION_HEADER 를 읽음.
  • 메모리 할당: 원하는 베이스(혹은 OS가 제공하는 임의 베이스)에 실행/읽기/쓰기 권한으로 전체 이미지 크기 만큼 할당.
  • 섹션 복사: 각 섹션의 원본(raw) 데이터를 대상 메모리에 적절한 오프셋으로 복사.
  • Relocations 적용: 만약 로드 베이스가 PE의 preferred base와 다르면 BASE_RELOCATION 테이블을 읽어 각 주소를 (newBase - preferredBase) 만큼 조정.
  • Imports 해결: PE의 Import Directory를 순회, 각 의존 DLL 이름을 확인 → 그 DLL이 아직 로드되지 않았으면 로드(Reflective case에서는 직접 로드 루틴을 포함). 각 import function 이름/ordinal에 대해 해당 DLL의 Export Table을 스캔해 실제 함수 주소를 찾아 IAT 슬롯에 써 넣음.
  • TLS(쓰레드 로컬 저장소) 처리: TLS 콜백이 있으면 이를 처리(특정 구현에서 생략하면 문제가 발생).
  • DllMain 호출: DllMain(혹은 PE의 entrypoint)을 실행(단, DllMain 내부에서 특정 API 호출 제약이 있어 안전 고려 필요).
  • 자체 로더(Reflective loader): DLL 안에 자신의 로더 코드를 포함시켜 외부 API 없이도 위 과정을 수행하도록 하는 기법이 흔함.

이 과정은 OS의 표준 로더가 수행하는 작업을 수동으로 재현하는 것과 같으며, 따라서 구현상 실수가 발생하기 쉽습니다(예: TLS 미처리, 잘못된 Relocation).


6) 포렌식·탐지 지표(What to look for)

방어/탐지 관점에서 실무적으로 체크해야 할 항목들:

  • 비정상적인 원격 스레드 생성: 프로세스 간 CreateRemoteThread 호출/이벤트.
  • 메모리 내 비파일 기반 모듈: VirtualQuery로 확인되는 실행 가능한(EXECUTE) 메모리 영역에 파일 경로가 없는 경우.
  • 스레드 시작 주소가 모듈 내부가 아님: 스레드 시작 지점이 로드된 모듈의 코드 섹션 주소가 아닌 경우(즉, 임의 메모리 영역).
  • 변조된 IAT / 후킹 징후: API 함수 주소가 정상 모듈이 아닌 다른 주소를 가리킴.
  • 레지스트리·자동 로드 엔트리: AppInit_DLLs, Image File Execution Options, Run keys 등.
  • 실행 시간 불일치: 프로세스 모듈의 파일 타임스탬프와 로드 타임 불일치.
  • 네트워크/파일 활동과 동시 발생: 메모리에서 로드된 코드가 네트워크 연결을 시도하거나 파일을 생성하는 경우.
  • Sysmon(시스템 모니터) 이벤트: 파일less 기법, 프로세스 인젝션 관련 이벤트(예: CreateRemoteThread, CreateProcess, Load Image 등)를 수집·상관분석.

도구: Sysinternals(예: Process Explorer, Process Monitor), EDR 제품, Sysmon(시스템 모니터) 로그 수집기를 이용.


7) 방어 및 완화(권장)

  • 최소권한 원칙: 프로세스/사용자 권한 최소화, SeDebugPrivilege 같은 권한 제한.
  • 코드 무결성/서명 강제화: Windows Defender Application Control(WDAC, Windows Defender 응용 프로그램 제어) 또는 AppLocker로 서명되지 않은 DLL 로드 차단.
  • 프로세스 완화 정책: Process Mitigation Policies를 사용해 원격 스레드 생성이나 디버깅을 제한.
  • 메모리 보호: DEP(Data Execution Prevention, 데이터 실행 방지), ASLR(Address Space Layout Randomization, 주소 공간 레이아웃 무작위화), CFG(Control Flow Guard, 제어 흐름 보호) 활성화.
  • EDR/HIPS 배포: 엔드포인트 탐지 및 대응(Endpoint Detection and Response, EDR), 호스트 침입 방지 시스템(Host Intrusion Prevention System, HIPS)으로 비정상 원격 메모리 조작·스레드 생성 탐지.
  • 로그·모니터링: Sysmon(시스템 모니터) 규칙(원격 쓰기, CreateRemoteThread, VirtualAllocEx/WriteProcessMemory 패턴 등)으로 수집·알림.
  • 레지스트리 감시: 자동 로드 관련 레지스트리 키 변조 감시.
  • 화이트리스트 모델: 신뢰된 소프트웨어-드라이버만 허용(특히 서버/중요 단말).

8) 합법적 사용 사례

  • 디버깅·프로파일링 도구(예: Visual Studio의 디버거 확장, 성능 분석 도구)가 타깃 프로세스에 코드를 주입해 심층 분석.
  • 합법적 후킹(예: 보안 소프트웨어, 모니터링 에이전트, 접근성 도구) — 단, 서명/정책에 따라 허용.
  • 테스트 환경에서의 침투테스트(허가된 범위 내)와 적대적 공격 대응 훈련.

9) 기술사/시험 대비용 요약(암기 포인트)

  • DLL 인젝션 정의와 목적(권한획득, 후킹, 은닉).
  • PE 로딩 기본 단계(매핑 → imports resolve → relocation → entrypoint).
  • 주요 기법 5~7개(LoadLibrary+RemoteThread, SetWindowsHookEx, APC, Thread Hijacking, Process Hollowing, Manual Mapping, Kernel-mode).
  • Manual Mapping 핵심: 섹션 복사 → relocations → imports resolve → TLS/DllMain 처리.
  • 탐지 인디케이터: 원격 스레드, 비파일 모듈, IAT 변조, 레지스트리 자동 로드.
  • 방어: 권한 제한, 코드 서명, Process Mitigations, DEP/ASLR/CFG, EDR + 로깅(Sysmon).

10) 끝맺음 & 추가 제공 가능 항목

원하시면 다음 중 하나를 선택 없이 바로 제공하겠습니다(추가 요청 없이 바로 생성해 드릴 수 있음):

  • A) 각 인젝션 기법 별 상세 플로차트(순서도) — 방어 포인트 포함.
  • B) 포렌식·탐지 체크리스트(운영팀이 바로 적용 가능한 항목 집합).
  • C) Manual Mapping의 개념적 의사코드(pseudocode) — 방어·분석 목적으로만, 실제 실행 가능한 코드는 아님.
  • D) 특정 기법(예: LoadLibrary 방식)과 관련한 탐지 규칙 예시(Sysmon 이벤트 기반) — 방어 관점.
profile
DevSecOps, Pentest, Cloud(OpenStack), Develop, Data Engineering, AI-Agent

0개의 댓글