📖
레드팀 플레이북
깃허브기여하는 방법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
  • 문제 & 해결
  • FreshyCall
  • 코드
  • 마치며
  • 레퍼런스
  1. Personal-Research
  2. README-and-Template

FreshyCall

PreviousHalosGate

Last updated 2 years ago

Disclaimer

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

블로그 링크:

툴/코드 링크:

문제 & 해결

  • FreshyCall은 다른 기법들의 문제를 해결하려고 나온 기법은 아니다. 그저 ntdll.dll의 exported 된 NTAPI 함수들과 그 메모리주소를 보고 있자니, 특정한 패턴이 보이길래 나온 기법이다.

FreshyCall

  • FreshyCall 은 ntdll.dll 이 export하고 있는 NTAPI 함수들의 메모리 주소를 정렬해봤을 때, 시스템 콜 번호가 0부터 시작해 순차적으로 늘어난다는 개념을 통해 런타임 중 다이나믹 하게 NTAPI 함수의 시스템 콜 번호를 찾아내는 기법이다.

  • Hell's Gate와 Halos Gate에서 살펴봄 봐와 같이, NTAPI 함수들은 메모리상의 ntdll.dll 안에 순차적으로 exported 되어있으며 각 함수들은 32 바이트(0x20)씩 떨어져 있다. 예를 들어, ntdll의 가장 첫번째 함수인 NtAccessCheck 와 NtWorkerFactoryWorkerReady를 살펴보면 다음과 같다.

// 첫번째 NTAPI - 00007ffa`f566ec40 부터 시작하는 NtAccessCheck
0:000> uf ntdll!NtAccessCheck
ntdll!NtAccessCheck:
00007ffa`f566ec40 4c8bd1          mov     r10,rcx
00007ffa`f566ec43 b800000000      mov     eax,0    // 시스템 콜 번호 0
00007ffa`f566ec48 f604250803fe7f01 test    byte ptr [SharedUserData+0x308 (00000000`7ffe0308)],1
00007ffa`f566ec50 7503            jne     ntdll!NtAccessCheck+0x15 (00007ffa`f566ec55)  Branch

// 두번째 NTAPI - 00007ffa`f566ec60 부터 시작하는 NtWorkerFactoryWorkerReady
ntdll!NtWorkerFactoryWorkerReady:
00007ffa`f566ec60 4c8bd1          mov     r10,rcx
00007ffa`f566ec63 b801000000      mov     eax,1    // 시스템 콜 번호 1
00007ffa`f566ec68 f604250803fe7f01 test    byte ptr [SharedUserData+0x308 (00000000`7ffe0308)],1
00007ffa`f566ec70 7503            jne     ntdll!NtWorkerFactoryWorkerReady+0x15 (00007ffa`f566ec75)  Branch
  • 그리고 이들의 시스템 콜 번호는 0부터 시작해 순차적으로 1씩 증가한다.

  • 그렇다면 ntdll.dll 이 export 하고 있는 모든 함수들을 메모리 낮음 -> 높음 상태로 정렬한 뒤, 시스템 콜 번호를 0부터 XXX까지 부여한 딕셔너리/맵/배열을 만들면, 언제든지 원하는 시스템 콜 번호를 가져올 수 있게 된다.

코드

  • 아래의 코드는 모두 원본 코드들 (https://github.com/Crummie5/FreshyCalls, https://alice.climent-pommeret.red/posts/direct-syscalls-hells-halos-syswhispers2/) 참고해 재구성한 코드다.

  • 먼저 PEB -> LoaderData + InMemoryOrderModuleList.Flink -> Flink 콤보와 함께 Dos/NT/Optional/ExportTable 를 통해 exported 함수들의 AddressofFunction, AddressofName, AddressofNameOrdinals 테이블 3개를 가져오는 코드는 Hell's Gate와 동일하다.\

  • 이후 Ordinal을 통해 AddressOfFunction을 낮음 -> 높음 순서대로 정렬해준다. Exported Functions 들은 테이블을 3개나 가지고 있는데, 이때 AddressOfFunction[ordinal] 식으로 메모리 주소를 빼내오는게 가장 낮은 메모리 주소부터 높은 메모리 주소까지 정렬을 할 수 있는 방식이다.

// Various export tables from ntdll 
DWORD* FuncAddr_Table = (DWORD*)(ImageBase + ExportTable->AddressOfFunctions);
DWORD* Names_Table = (DWORD*)(ImageBase + ExportTable->AddressOfNames);
WORD* Names_Ordinal_Table = (WORD*)(ImageBase + ExportTable->AddressOfNameOrdinals);
DWORD numOfNtNames = 0;

// cpp map orders the key sequentially by default - til. 
// Map to store ntapi functionaddr:functionname
std::map<DWORD, std::string> funcAddrNameMap;
std::map<DWORD, std::string> funcNameSortedMap;
std::map<std::string, DWORD> funcNameSyscallMap;

// Populate each maps with funcAddr, funcName
for (int i = 0; i < ExportTable->NumberOfNames; i++) {
	DWORD nameOffset = Names_Table[i];
	WORD ordinal = Names_Ordinal_Table[i];
	DWORD functionAddr = (DWORD)(ImageBase + FuncAddr_Table[ordinal]);
	char* funcName = (char*)(ImageBase + nameOffset);

	if (strncmp(funcName, "Nt", 2) == 0 && strncmp(funcName, "Ntdll", 5) != 0 &&
		strncmp(funcName, "NtGetTickCount", 14) != 0) {
		printf("[+] funcName: %s\n", funcName);
		funcAddrNameMap[functionAddr] = funcName;
	}
}
  • 코드를 보면 cpp의 std::map 을 통해 파이썬의 딕셔너리 비슷한 맵을 만들고 있다. Exported 함수의 이름은 ImageBase + Names_Table[i] 를 통해 가져오고, 가장 중요한 메모리 주소는 ImageBase + FuncAddr_Table[ordinal] 을 통해서 가장 낮은 주소부터 가져오고 있다.\

  • 그 뒤 조건문을 이용해 Nt 로 시작하는 함수들만, Ntdll 와 NtGetTickCount 는 제외한채, 맵에다가 functionAddr 부터 넣어 낮은 메모리주소 -> 높은 메모리주소까지 정렬 시킨 뒤, 그에 맞는 Exported 함수의 이름을 넣어주고 있다.\

  • 이렇게 FunctionAddr:FunctionName 형태의 맵을 만들었다면, 메모리 주소를 바탕으로 이제 FunctionName:Syscall-Number 형태의 또 다른 맵을 만들면 된다. cpp 의 맵은 기본적으로 키 (Key) 를 기준으로 정렬을 시켜버리기 때문에, 두번째 맵을 그대로 만들면 FunctionName 의 알파벳 순서대로 시스템 콜 번호를 부여해버린다. 따라서 세번째 맵을 만들어 FunctionAddr 순서 그대로 FunctionName 이 정렬하게 한 뒤, 시스템 콜 번호를 부여해준다.\

  • 말로하면 복잡해보이지만 실제 코드는 간단하다.

// Populate funcNameSyscallMap with funcName sorted based on the address (lowest to highest) from funcAddrNameMap.
for (auto& kv : funcAddrNameMap) {
	funcNameSortedMap[kv.first] = kv.second;
}

DWORD syscallNumber = 0;
for (auto& kv : funcNameSortedMap) {
	funcNameSyscallMap[kv.second] = syscallNumber;
	syscallNumber++;
}

// Print stuff out 
printf("[+] Function Name:                                Syscall Number:\n");
for (auto& kv : funcNameSyscallMap) {
	printf("[+] %-*s %d\n", 50, kv.first.c_str(), kv.second);
}	

위의 코드를 실행하면 Exported 함수 이름과 그에 맞는 시스템 콜 번호가 들어간 맵의 출력 결과를 볼 수 있다. 이제 시스템 콜 번호가 필요할 때마다 이 맵에서 함수 이름을 검색해 번호를 찾아내면 된다. 아래의 맵은 보기 좋으라고 또 다시 번호대로 정렬 했지만, 어차피 해시맵 개념의 맵이기 때문에 큰 의미는 없다.

마치며

FreshyCall은 NTAPI 함수들의 메모리 주소와 시스템 콜 번호와의 상관관계지, 공격 기법이나 방어 우회 기법으로 보기는 힘들다. Hell's Gate나 Halos Gate에 비교해봤을 때 간단하지만 효과적인 개념으로 시스템 콜 번호를 구할 수 있다. 윈도우 운영체제의 ntdll exported 함수들의 메모리주소와 시스템 콜 번호들이 계속해서 순차적인 정렬 방식을 유지한다면, FreshyCall은 추후 윈도우 버전에서도 쓰이는 기법이 되지 않을까 싶다.

  • Windows 11 Pro 22H2 - 03/28/2023 에서 테스트 됨

레퍼런스

  • https://github.com/Crummie5/FreshyCalls

  • https://www.crummie5.club/freshycalls/

  • https://alice.climent-pommeret.red/posts/direct-syscalls-hells-halos-syswhispers2/

최종 코드는 여기에 있다 - \

📖
https://www.crummie5.club/freshycalls/
https://github.com/Crummie5/FreshyCalls
https://github.com/ChoiSG/RTPSourceCodes/blob/main/cpp/freshyCallPOC/freshyCallPOC.cpp