📖
레드팀 플레이북
깃허브기여하는 방법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
  • 문제
  • 해결
  • 중요 개념 - 프로그래매틱하게 시스템 콜 번호 찾기
  • 코드 - 시스템 콜 번호 찾기 - 개념
  • 적용
  • 예시
  • 마치며
  • MISC - 혼잣말
  1. Personal-Research
  2. README-and-Template

HellsGate

PreviousREADME-and-TemplateNextHalosGate

Last updated 2 years ago

Disclaimer

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

페이퍼 링크:

툴/코드 링크:

문제

  • AV/EDR의 유저랜드 후킹을 우회하기 위해 시스템 콜을 이용하는데, 이를 위해서는 각 NTAPI 함수들의 시스템 콜 번호를 알아야한다. Hell's Gate 발표 전까지 이 번호들을 런타임 중 프로그래매틱 하게 찾아낼 수 있는 방법이 없었다.

  • 따라서 레드팀들은 모든 윈도우 버전의 모든 시스템 콜 번호들을 스태틱하게 구조체로 만들어 하드코딩 + 수많은 조건문을 이용해 시스템 콜을 사용하고 있었다. 물론, 이는 매우 불안정하고 비효율적인 방법이였다.

해결

  • HellsGate (헬즈 게이트)는 NTAPI 함수들의 시스템 콜 번호를 런타임 도중 프로그래매틱하게 찾아주는 기법을 문서화 + POC화 시킨 연구다. 헬즈 게이트 덕분에 추후 수많은 XYZ 게이트 기법들이 생겨나며 시스템 콜 시대가 시작된다.

중요 개념 - 프로그래매틱하게 시스템 콜 번호 찾기

  • HellsGate의 중요 개념은 ntdll의 export된 NTAPI 함수의 시스템 콜 관련 바이트 패턴(mov r10, rcx // mov eax, <syscall-number>)의 시작지점으로부터 index로 5번째 (0부터 시작 기준, 실제로는 6번째 바이트) 바이트를 bitwise shift left 8 연산을 한 뒤, index로 4번째 (0부터 시작 기준, 실제로는 5번째 바이트) 바이트를 OR 연산을 하면 시스템 콜 번호를 프로그래매틱하게 구할 수 있다는 것이다.

페이퍼의 예시를 보자면, NtPlugPlayControl 함수의 시작 지점으로 부터의 명령어들은 4c 8b d1 b8 32 01 00 00 이다. 각각의 명령어들은 다음과 같이 풀이된다.

0:000> uf ntdll!NtPlugPlayControl  
ntdll!NtPlugPlayControl:  
00007fff`b040d3b0 4c8bd1 mov r10,rcx       // 인덱스 기준 0,1,2     - 4c 8b d1
00007fff`b040d3b3 b832010000 mov eax,132h  // 인덱스 기준 3,4,5,6,7 - b8 32 01 00 00

이때, 0부터 시작하는 인덱스 기준으로 5번째 0x01 바이트를 bitwise shift left 8 연산 후, 인덱스로 4번째 바이트 0x32 로 OR 연산을 하면 다음과 같이 된다.

// 01 == 5번째 바이트, 32 == 4번째 바이트 
(0x01 << 8) | 0x32 = 132h

// 풀이
0x01 << 8 == 0x0100 
0x0100 | 0x32 == 0x132h 

페이퍼에서도 Windbg를 통한 풀이를 다음과 같이 보여준다.

0:000> db (ntdll!NtPlugPlayControl + 0x4) L2
00007fff`b040d3b4 32 01 2.    // 32 == 4번째 바이트, 01 == 5번째 바이트 
0:000> ? (0x01 << 8) | 0x32
Evaluate expression: 306 = 00000000`00000132

코드 - 시스템 콜 번호 찾기 - 개념

위 개념/공식은 Hell's Gate 의 공식 깃헙 리포 main.c 의 GetVxTableEntry 함수에 적용되어 있다.

// main.c, line: 143~156 https://github.com/am0nsec/HellsGate/blob/master/HellsGate/main.c#L143-L156

// First opcodes should be :
//    MOV R10, RCX
//    MOV RCX, <syscall>
if (*((PBYTE)pFunctionAddress + cw) == 0x4c
	&& *((PBYTE)pFunctionAddress + 1 + cw) == 0x8b
	&& *((PBYTE)pFunctionAddress + 2 + cw) == 0xd1
	&& *((PBYTE)pFunctionAddress + 3 + cw) == 0xb8
	&& *((PBYTE)pFunctionAddress + 6 + cw) == 0x00
	&& *((PBYTE)pFunctionAddress + 7 + cw) == 0x00) {
	BYTE high = *((PBYTE)pFunctionAddress + 5 + cw);
	BYTE low = *((PBYTE)pFunctionAddress + 4 + cw);
	pVxTableEntry->wSystemCall = (high << 8) | low;
	break;
}

먼저, 제대로 시스템 콜 번호 관련 명령어가 있는 부분까지 왔는지 조건문을 통해 확인한다. pFunctionAddress의 0, 1, 2, 3 번째 오프셋이 4c 8b d1 b8 인지 알아본다. 이는 move r10, rcx, mov 까지의 어셈 코드를 나타낸다. 그 뒤, 6번째와 7번째 오프셋이 00 00 인지도 확인하고 있다. 6번째와 7번째 바이트를 확인하는 이유는 mov eax, <syscall>h 가 실행될 경우 인덱스로 6번째와 7번째 오프셋의 바이트들은 무조건 00 00 이 되기 때문이다.

0,1,2,3,6,7 번의 바이트를 모두 확인했고, 조건문을 통과했다면, 우리가 찾고 있던 시스템 콜 관련 명령어 "패턴" 을 찾은 것이다.

// 시스템 콜 관련 명령어 "패턴" 
mov r10, rcx
mov rcx, <syscall>

이제 남은 4번째, 5번째 바이트와 Hell's Gate의 시스템 콜 번호 찾기 공식을 이용해 시스템 콜 번호를 찾는다. 앞서 얘기한대로, 인덱스(NT함수의 시작지점)로부터 5번째 바이트는 bitwise shift left 8 연산을, 그 뒤에 4번째 바이트는 OR 연산을 실행한다. 그 뒤, 찾아낸 시스템 콜 번호를 pVxTableEntry->wSystemCall 에다가 저장한다.

BYTE high = *((PBYTE)pFunctionAddress + 5 + cw);
BYTE low = *((PBYTE)pFunctionAddress + 4 + cw);
pVxTableEntry->wSystemCall = (high << 8) | low;

적용

  • 시스템 콜 번호는 찾았다. 근데 이건 어떻게 사용되는걸까?

  • Hell's Gate 가 NT 함수들의 메모리 주소, 함수 해시, 시스템 콜 번호를 편리하게 저장하기 위한 _VX_TABLE_ENTRY 와 _VX_TABLE 에 관련된 설명은 생략한다.

  • 일단 VX_TABLE 및 엔트리들을 최대한 설정해준 뒤, GetVxTableEntry 함수를 이용해 위에서 설명한 개념을 이용해 시스템 콜을 찾는다.

  • 그 뒤, HellsGate 과 HellDescent 어셈블리 코드들을 이용해 실제로 시스템 콜을 실행한다.

.data
	wSystemCall DWORD 000h

.code 
	HellsGate PROC
		mov wSystemCall, 000h
		mov wSystemCall, ecx
		ret
	HellsGate ENDP

	HellDescent PROC
		mov r10, rcx
		mov eax, wSystemCall

		syscall
		ret
	HellDescent ENDP
end

HellsGate 는 GetVxTableEntry 함수에서 찾아낸 시스템 콜을 wSystemCall 이라는 변수에 저장한다. HellDescent 는 실제 NT 함수들처럼 mov r10, rcx // mov eax, <systemcall>h // syscall 를 통해 eax 레지스터에 시스템 콜 번호를 올려놓은 뒤, syscall 명령어를 실행해 CPU에게 커널 모드로 진입해 해당 syscall 을 실행시킨다.

예시

페이퍼에서 나온 간단한 예시다. 예를 들어, NtAllocateVirtualMemory 의 시스템 콜 번호를 알아낸 뒤, 이를 직접 어셈블리 코드를 이용해 사용해보자.

// VX_TABLE 의 Entry 중 하나인 NtAllocateVirtualMemory의 시스템 콜을 GetVxTableEntry 함수를 이용해 찾아냄. 
VX_TABLE Table = { 0 };
Table.NtAllocateVirtualMemory.dwHash = 0xf5bd373480a6b89b;
if (!GetVxTableEntry(pLdrDataEntry->DllBase, pImageExportDirectory, &Table.NtAllocateVirtualMemory))
	return 0x1;

// NtAllocateVirtualMemory의 시스템 콜 번호를 HellsGate + HellDescent 콤보를 이용해 실행 
HellsGate(pVxTable->NtAllocateVirtualMemory.wSystemCall);
status = HellDescent((HANDLE)-1, &lpAddress, 0, &sDataSize, MEM_COMMIT, PAGE_READWRITE);

마치며

헬즈 게이트는 2018~2020년 유저랜드 후킹 및 시스템 콜 관련된 포스트들이 많이 나올때 프로그래매틱하게 시스템 콜 번호를 찾아내는 방법을 깔끔한 문서화 + POC 코드까지 제공한 전설적인(?) 연구다.

헬즈 게이트 이후 수많은 XYZ게이트 기법들이 쏟아져 나오기도 했다. 추후 나온 기법들에 비하면 부족하기는 하지만, 게이트 기법들의 선조격이자 처음으로 나온 기법이니 이해된다. 다시 한 번 페이퍼를 읽으면서 저자들의 지식에 감탄했다.

MISC - 혼잣말

  • GetVxTableEntry 에서 cw 변수가 왜 quick and dirty fix in case the function has been hooked 인지 몰랐는데, 말이 된다. NT함수의 시작지점 오프셋이라고도 볼 수 있는 cw를 하나씩 증가하며 NTAPI 함수의 메모리를 시작부터 1바이트씩 쭉 훑으면서 조건문을 통해 mov r10, rcx // mov 패턴의 명령어들을 찾는다. 이렇게 되면 NT 함수 초반 부분에 훅을 걸어놓건 뭘 하던 간에 어쨌든 "난 mov r10, rcx // mov 패턴을 가진 바이트들만 찾는다" 느낌으로 쭉 메모리를 훑게 된다. 후킹을 우회할 수 있게 된다는게 무슨 말인지 알겠다.

📖
https://vxug.fakedoma.in/papers/VXUG/Exclusive/HellsGate.pdf
https://github.com/am0nsec/HellsGate