📖
레드팀 플레이북
깃허브기여하는 방법WhoAreWe블로그
  • 레드팀 플레이북
  • 레드팀이란
  • 레드팀 글로벌 동향 (2024)
  • 베이직 레드팀(Basic Redteam)
    • 개요
    • 1. 공격자 인프라 구성
    • 2. 초기 침투
    • 3. 정보 수집
    • 4. 권한 상승 - US
    • 5. 횡적 이동: USWKSTN01 -> SQL01
    • 6. 권한 상승 - SQL01
    • 7. 도메인 장악 WEB01
    • 8. US -> RT 장악
    • 9. RT -> DEV 정보 수집
    • 10. 권한 상승 및 목표 달성
  • 🚧인프라 (Infrastructure)
    • 개념
    • 예시 인프라
    • 팀 서버 - Sliver
      • 스테이저 (Stager) 사용
    • 도메인 분류와 신뢰도
    • HTTP 리다이렉터
    • HTTPS 리다이렉터
    • SMTP Gophish + Mail
    • SMTP Gophish + ESP
    • SMTP Gophish + Relay + ESP
    • 인프라 구축 자동화
      • 테라폼 (Terraform)
      • SMTP 테라폼 자동화
      • HTTPS 리다이렉터 자동화 (AWS)
    • old-네뷸라를 이용한 인프라 구축
      • 도메인과 리다이렉터 설정
      • 중립 공간 (클라우드) 설정
      • 네뷸라 (Nebula)
      • 네뷸라 설정
    • 도메인 프론팅 (Domain Fronting)
    • 도메인 프론팅 - Azure Edgio CDN
    • Cloudflared Tunnel과 Worker
    • Cloudflared Tunnel과 Pages
  • 🔎초기 정찰
    • 개념
    • 타겟 발견
    • OSINT
      • 작전보안
      • 자산 정보 수집
      • 구글 도킹
  • ⚔️초기 침투 (Initial Access)
    • 개념
    • 피싱 첨부파일
      • 오피스 VBA 매크로
      • XLM Excel 4.0 매크로
      • 원격 템플렛 인젝션
      • VBA Stomping
      • HTA
      • LNK
      • ISO
      • VBA Purging - TODO
      • DotNetToJS - TODO
      • Follina - TODO
    • HTML 스머글링 (Smuggling)
    • 피싱 - AitM (Adversary in the Middle)
    • Living Off Trusted Sites (LOTS)
  • 🐳정보 수집 - 내부망
    • 개념
    • 로컬 호스트 정보 수집
    • 블러드하운드
    • SMB 쉐어 수집
    • 정보 수집 - 파워쉘
    • 정보 수집 - C# - TODO
    • 커버로스 유저 이름 정보수집
    • CME - 호스트이름과 IP주소
    • LDAP Anonymous Bind
  • 🐴실행 (Execution)
    • 개념
    • 파워쉘
      • 인메모리 실행
      • C# 실행
      • 윈도우 API 실행
    • LOLBAS
    • Native API - TODO
  • 🙃지속성 (Persistence)
    • 개념
    • 골든 티켓 (Golden Ticket)
    • DLL 사이드로딩 (DLL Side-Loading)
    • DLL Search Order Hijacking - TODO
    • 레지스트리 / 스타트업 폴더
  • ⬆️권한 상승
    • 개념
    • AD 권한 상승
      • Active Directory Certificate Services (ADCS)
        • ESC1
        • ESC8
      • Shadow Credentials
      • noPac
      • Kerberoasting
      • AS-REP Roasting
      • DHCPv6 포이즈닝
      • Resource-Based Constrained Delegation (RBCD)
      • SCCM
    • AD-DACL
      • AddAllowedToAct
      • AddKeyCredentialLink
      • GenericAll
      • GenericWrite
      • WriteDACL
      • AllExtendedRights
      • WriteAccountRestrictions
      • WriteOwner
      • AddMember
    • 로컬 권한 상승 - TODO
      • 잘못된 서비스 설정
      • Unquoted Service Path
      • Always Install Elevated
      • PrintNightmare
  • 🐍보안 우회 (Defense Evasion)
    • 쉘코드 암호화
    • 런타임 다이나믹 링킹 (Run-time Dynamic Linking)
    • AMSI 우회
    • 유저랜드 후킹 - 역사
    • 유저랜드 커널랜드 윈도우API 개념
    • 유저랜드 후킹
    • DInvoke - 시스템 콜
    • 페이로드 크기
    • 가변적 C2 프로필
    • 프로세스 인젝션
      • CreateRemoteThread
      • NtMapViewOfSection
    • 간단 디펜더 우회 - 쉘코드
    • 간단 디펜더 우회 - C#
    • MSIExec
    • 다형성 코드
  • 👿후속 공격 (Post Exploitation)
    • 후속 공격의 진화
    • External SID Golden Ticket
  • 🎭계정 정보 탈취 (Credential Access)
    • 커버로스
      • 커버로스팅 (Kerberoasting)
      • AS-Rep Roasting
    • 비밀번호 스프레이 공격
    • LLMNR/NBT-NS 포이즈닝
    • NTLM 릴레이 (NTLM Relay)
      • SMB to SMB
      • SMB to LDAP/S
      • HTTP to LDAP
      • SMB to HTTP
      • SMB to SCCM
    • 강제 인증 (Authentication Coercion)
      • MS-RPRN - Printerbug / Print Spooler
      • MS-EFSRPC - Petitpotam
      • MS-FSRVP - ShadowCoerce
      • MS-DFSNM - DFSCoerce
    • NTLM 다운그레이드
    • DHCPv6 포이즈닝
    • LAPS - TODO
    • DCSync
    • DPAPI
  • ↔️횡적 이동 (Lateral Movement)
    • 개념
    • Pass-the-Hash
    • SMB 와 PsExec
    • WMI
    • WinRM / Powershell Remoting
    • RDP
    • SSH Port Forwarding & Tunneling
    • Dynamic Port Forwarding & ProxyChains
    • 네트워크 피버팅 - 툴
    • Network Pivoting (피벗) - TODO
  • 개념
    • 윈도우 사용자 인증
      • NTLM 인증
      • 커버로스 (Kerberos) 인증 - TODO
      • ADCS 인증서 기반 인증
    • AD 관련 용어 해설
  • 실 공격 TTP와 대응방안 - TODO
    • 개념
  • 🧑‍🔬홈 랩 (Home lab)
    • 시스몬 (sysmon) 설치
    • SIEM과 EDR 솔루션 설치
    • 취약한 랩을 위한 설정 커맨드
    • 말웨어 자동 분석툴 Cuckoo 샌드박스 설치
  • 기본 개념
    • DNS
      • 사이버 보안에 필요한 DNS 개념 편 #1
      • 해킹에 필요한 DNS 공격 & 우회 기법 편 #2
      • 방어에 필요한 DNS 탐지 편 #3
  • 웹 & 모바일
    • 01-계정관리
      • 통신 과정 흐름 훑어보기
      • 첫번쩨, payload설정 방법
      • 두번째, 세션을 유지하는 방법
      • CSRF Token에 관하여
      • 세번째, OWASP Juice Shop 로그인 페이지에서의 통신 흐름과 구조 알아보기
  • 🎅MISC
    • Host-based 공격 CheatSheet (FEAT. OSCP)
      • Enumeration (정보 수집 및 열거)
      • Exploitation (공격)
      • Post Exploitation (후속공격)
    • Changelog
    • 기여하는 방법
    • 레퍼런스와 크레딧
    • C# snippets
    • winapi 리스트
      • original notes from obsidian
    • 파워쉘 원라이너 (oneliner)
  • 📖Personal-Research
    • README-and-Template
      • HellsGate
      • HalosGate
      • FreshyCall
Powered by GitBook
On this page
  • Disclaimer
  • 문제
  • 해결
  • 중요 개념 - NTAPI들의 시스템 콜 번호 패턴
  • 코드
  • 적용과 예시
  • 마치며
  • 레퍼런스
  1. Personal-Research
  2. README-and-Template

HalosGate

PreviousHellsGateNextFreshyCall

Last updated 2 years ago

Disclaimer

이곳은 제 개인 공부 + 연구 섹션입니다. 오펜시브 시큐리티 관련 블로그 글을 읽고, 요약한 뒤, 거기에 있는 코드들 따라치기 정도의 낮은 퀄리티 글 밖에 없을거기 때문에 안 읽으셔도 무방합니다. 이 섹션의 모든 페이지들의 내용 및 코드는 제것이 아닙니다.

블로그 링크:

툴/코드 링크:

문제

  • HellsGate에서 다이나믹하게 시스템 콜 번호를 가져올 때 가장 중요했던 점 중 하나는 바로 mov r10, rcx // mov eax,<syscall#> 형식의 시스템 콜 번호 바이트 패턴 - 4c 8b d1 b8 <syscall> <syscall> 00 00 을 찾는 것이였다.

  • 바이트 패턴은 깔끔한 ntdll.dll 의 경우에는 쉽게 찾을 수 있다. 하지만 유저랜드 후킹이 들어간 메모리상의 NTAPI 함수 메모리에서는 바이트 패턴이 완전히 바뀌어 버린 경우가 많이있다. 이 경우, 바이트 패턴 자체를 아예 찾지 못하기 때문에 HellsGate 기법을 사용할 수 없게 된다.

해결

  • Halos Gate (헤일로즈 게이트)는 시스템 콜 번호를 찾고자 하는 NTAPI 함수가 유저랜드 후킹이 된 경우, 해당 함수 위/아래에 있는 "이웃" 함수들에게서 바이트 패턴을 찾고, Hells Gate를 이용해 시스템 콜 번호를 찾아낸 뒤, 간단한 더하기/빼기를 이용해 찾고자 하는 NTAPI 함수의 시스템 콜 번호를 찾는 기법이다.

중요 개념 - NTAPI들의 시스템 콜 번호 패턴

  1. NTAPI 함수들의 시스템 콜 번호는 0부터 시작해, 순차적으로 1씩 증가한다.

  2. AV/EDR 솔루션들은 모든 NTAPI 함수들에 유저랜드 후킹을 걸어놓지 않는다.

  3. 따라서, 만약 찾고자 하는 함수에 유저랜드 후킹이 걸려있다면, 메모리상으로 위로 올라가거나, 아래로 내려가서 "이웃" NTAPI 함수들에게서 바이트 패턴을 찾고, 시스템 콜 번호를 찾은 뒤, 올라간/내려간 함수 갯수만큼 시스템 콜 번호를 더하거나/빼면, 찾고자 하는 함수의 시스템 콜 번호를 논리적으로 찾아낼 수 있다.

  • 원문 글의 예시를 살펴보자.

ZwMapViewOfSection 함수의 시스템 콜 번호를 찾으려고 하는데, 이미 AV/EDR 솔루션에서 유저랜드 후킹을 걸어버렸다. mov r10,rcx // mov eax, <syscall#> 바이트 패턴을 찾을 수 없는 상태다.

하지만 메모리상 ZwMapViewOfSection 의 바로 위에 있는 ZwSetInformationFile 의 경우는 유저랜드 후킹이 걸려있지 않다. 이 함수에서는 시스템 콜 번호 바이트 패턴 mov r10, rcx // mov eax,<syscall#> == 4c 8b d1 b8 <syscall> <syscall> 00 00 를 찾을 수 있다.

이제 HellsGate 공식을 이용해 ZwSetInformationFile 의 시스템 콜 번호를 다이나믹하게 찾는다. 27이 나온다.

// 시스템 콜 번호 바이트 패턴 
0  1  2  3  4  5  6  7  
4c 8b d1 b8 27 00 00 00 

// 5번째 바이트 bitwise shift left 8 | 4번째 바이트 
(00 << 8) | 27 == 27 
  1. ZwSetInformationFile 은 ZwMapViewOfSection 의 바로 "위" 에 있던 이웃 함수였다.

  2. ZwSetInformationFile 의 시스템 콜 번호는 27이다.

  3. NTAPI 함수들의 시스템 콜 번호는 순차적으로, 1씩 증가한다.

  4. ZwMapViewOfSection 은 바로 "아래"에 있는 이웃 함수니, 시스템 콜 번호는 27 + 1 = 28이 된다.

만약 "이웃" 함수들도 후킹되어 있다면, 반복문을 통해 쭉쭉 위 (혹은 아래)에 있는 이웃 함수들을 살펴본다. 유저랜드 후킹이 되어 있지 않은 이웃 함수를 드디어 찾았다면, 시스템 콜 번호를 찾아낸 뒤, 반복문의 루프 횟수 만큼 더하거나 빼주면 된다. (예. 4번째 아래에 있는 이웃함수에서 시스템 콜 바이트 패턴 확인. 시스템 콜 30 확인. 따라서 타겟은 30 - 4 = 26)

코드

각 NTAPI 함수들의 stub는 항상 32비트 (4바이트)로 일정하다. 따라서, 반복문 안에서 32비트씩 위로, 그 다음 아래로 100개(혹은 500개, 1000개, etc.)의 이웃 함수들을 루프하며 바이트 패턴을 찾을 때 까지 반복한다.

바이트 패턴을 가진 이웃 함수를 찾았다면 이웃 함수의 시스템 콜 번호를 구한다. 그 뒤, 위로 올라갔냐 아래로 내려갔냐를 따져 반복문의 인덱스 만큼 이웃 함수의 시스템 콜 번호에서 더하기/빼기를 해주면 원하던 함수의 시스템 콜 번호를 찾을 수 있다.

// NTAPI 함수들의 stub는 항상 32비트로 일정. 
int GoUp -32;
int GoDown 32;

// 첫 명령어가 e9 (jmp) 라면 후킹 되어 있다는 뜻. 이럴 경우 HalosGate 기법 시작. 
if (*((PBYTE)pFunctionAddress) == 0xe9) {
  // 반복문 실행, 인덱스 i 
  for (WORD index = 1; index <= 500; index++) {
    // 현 함수에서 인덱스 * 32비트를 이용해 "아래로" 내려감. 그 뒤, 시스템 콜 번호 바이트 
    // 패턴을 Hells Gate 조건문을 이용해 찾음. 
    if (*((PBYTE)pFunctionAddress + index * GoDown) == 0x4c
      && *((PBYTE)pFunctionAddress + 1 + index * GoDown) == 0x8b
      && *((PBYTE)pFunctionAddress + 2 + index * GoDown) == 0xd1
      && *((PBYTE)pFunctionAddress + 3 + index * GoDown) == 0xb8
      && *((PBYTE)pFunctionAddress + 6 + index * GoDown) == 0x00
      && *((PBYTE)pFunctionAddress + 7 + index * GoDown) == 0x00) {
      BYTE high = *((PBYTE)pFunctionAddress + 5 + index * GoDown);
      BYTE low = *((PBYTE)pFunctionAddress + 4 + index * GoDown);

      // "아래로" 내려갔으니, 이웃함수의 시스템 콜 번호에서 index 만큼 "빼기" == 타겟 함수의 시스템 콜 번호. 
      pVxTableEntry->wSystemCall = (high << 8) | low - index;
      return TRUE;
  	}
		
    // 이번엔 "위로" 올라감. 시스템 콜 번호 바이트 패턴을 HellsGate 조건문을 이용해 찾음. 
    if (*((PBYTE)pFunctionAddress + index * GoUp) == 0x4c
      && *((PBYTE)pFunctionAddress + 1 + index * GoUp) == 0x8b
      && *((PBYTE)pFunctionAddress + 2 + index * GoUp) == 0xd1
      && *((PBYTE)pFunctionAddress + 3 + index * GoUp) == 0xb8
      && *((PBYTE)pFunctionAddress + 6 + index * GoUp) == 0x00
      && *((PBYTE)pFunctionAddress + 7 + index * GoUp) == 0x00) {
      BYTE high = *((PBYTE)pFunctionAddress + 5 + index * GoUp);
      BYTE low = *((PBYTE)pFunctionAddress + 4 + index * GoUp);

      // "위로" 올라갔으니, 이웃함수의 시스템 콜 번호에서 index 만큼 "더하기" == 타겟 함수의 시스템 콜 번호. 
      pVxTableEntry->wSystemCall = (high << 8) | low + index;
      return TRUE;
    }
}

적용과 예시

Halos Gate는 Hells Gate에서 시스템 콜 번호를 찾는 논리만 강화된 기법이기 때문에 시스템 콜 번호를 찾은 뒤 사용하는 것 자체는 Hells Gate와 동일한 어셈블리 코드 양식을 사용한다. HellsGate 페이지를 참고한다.

마치며

헤일로즈 게이트 또한 부족한 점이 있기 때문에 추후 Tartarus Gate나 FreshyCalls 등의 기법들이 추가로 나오기도 했지만, 이는 또 다른 페이지에서 다뤄보도록 한다.

레퍼런스

아래의 코드는 모두 이 블로그 포스트 () 에서 가져왔음을 밝힌다.

헤일로즈 게이트는 maldev 쪽에서 유명한 강의를 제공하는 Sektor7()에서 발표한 기법이다. NTAPI 함수들이 순차적으로 1씩 증가한다는 점, NTAPI 함수들의 stub는 무조건 32비트로 일정하기 때문에 "올라갔다" "내려갔다" 하기가 쉽다는 점, 이웃 함수들의 존재로 간접적으로 타겟 함수의 시스템 콜 번호를 찾은 뒤, 더하기/빼기를 이용해 원하는 함수의 시스템 콜 번호를 찾는다는 점이 정말 똑똑하고도 흥미로운 발상이다.

📖
https://alice.climent-pommeret.red/posts/direct-syscalls-hells-halos-syswhispers2/#retrieve-syscall-id-dynamically
https://www.sektor7.net/
https://blog.sektor7.net/#!res/2021/halosgate.md
https://alice.climent-pommeret.red/posts/direct-syscalls-hells-halos-syswhispers2/#retrieve-syscall-id-dynamically
MDwiki
EDR Bypass : Retrieving Syscall ID with Hell's Gate, Halo's Gate, FreshyCalls and Syswhispers2Alice Climent-Pommeret
Sektor7 사 블로그 포스트 중 일부. 유저랜드 후킹 때문에 ZwMapViewOfSection에서 바이트 패턴을 찾아볼 수 없다.
Sektor7 사 블로그 포스트 중 일부. 유저랜드 후킹 때문에 ZwMapViewOfSection에서 바이트 패턴을 찾아볼 수 없다.
Sektor7사 블로그 포스트 중 일부. ZwSetInformationFile 에는 후킹이 안걸려있고, 바이트 패턴이 존재한다.
Logo