📖
레드팀 플레이북
깃허브기여하는 방법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
  • 개요
  • 예시
  1. 보안 우회 (Defense Evasion)

다형성 코드

by. @j0eun https://github.com/ChoiSG/kr-redteam-playbook/pull/5

개요

다형성 코드란 매번 컴파일 할 때마다 형태가 달라지는 코드를 말한다. 예를 들면, "A가 과일가게에서 사과를 산다" 라는 소스코드를 컴파일하면 생성되는 기계어 코드는 항상 달라야 한다. 다만, 형태가 달라진다고 해서 원본 소스코드의 기능이 바뀌어선 안된다. 쌩뚱맞게 A가 과일가게에서 두리안을 사버리면 안된다는 뜻이다.

다형성 코드를 사용하는 이유는 저마다 다르다. 악성코드는 안티바이러스 제품의 파일 해시(시그니처) 기반 탐지를 우회하기 위해 주로 사용한다. 해시 함수는 입력값이 1비트라도 달라지면 결과값이 크게 바뀌는 속성이 있다. 따라서 코드 또는 데이터의 일부를 아주 조금만 변경해도 파일 해시 기반 탐지를 우회할 수 있다. 프로텍터(엔드포인트 제품 보호)와 같은 보안 제품은 프로텍터 해제의 자동화를 어렵게 만들기 위해 사용하기도 한다.

이 페이지에서 퍼지 해시(Fuzzy hash)는 예외로 둡니다. 퍼지 해시는 입력값을 가지고 영역을 나누어 각자 따로 일반적인 해시값을 구한 뒤, 이들을 병합하는 방식입니다. 병합된 최종 해시값은 서로 다른 입력값이라 할지라도 유사도를 비교할 수 있습니다. 안티바이러스 분야에서는 악성코드 변종을 구분하는데 주로 사용됩니다.

어떻게 원본 소스코드의 기능을 훼손하지 않는 선에서 기계어 코드를 매번 다르게 생성할 수 있을까? 예시를 살펴보자.

예시

int main(void)
{
	int foo = 100;
	printf("%d\n", foo);    // 콘솔에 정수 100 출력
}

작고 귀여운 코드가 있다.

이 프로그램의 기능은 "콘솔에 100을 출력"하는 것이다. 기능을 훼손하지 않는 선에서 다형성을 적용시켜 보자.

// RandomSeed 함수 출처: Conti V3.0 랜섬웨어 소스코드
constexpr int RandomSeed(void)
{
	return '0' * -40271 + // offset accounting for digits' ANSI offsets
		__TIME__[7] * 1 +
		__TIME__[6] * 10 +
		__TIME__[4] * 60 +
		__TIME__[3] * 600 +
		__TIME__[1] * 3600 +
		__TIME__[0] * 36000;
};

int main(void)
{
	int foo = 100;
	int bar = RandomSeed();
	foo = foo + bar - bar;  // (bar - bar)의 결과는 0이므로 foo의 상태는 변화 없음
	printf("%d\n", foo);    // 콘솔에 정수 100 출력
}

생소할 수 있는 키워드들

  • constexpr <TYPE> : 컴파일 타임에 값이 결정되는 변수. 즉, 컴파일을 마치면 실행파일의 코드에 기호(변수)로 존재하지 않고 상수로 존재한다.

  • __TIME__ : Visual C/C++, GCC 등 컴파일러에서 지원하는 매크로이다. 전처리 과정에서 <hh:mm:ss> 형식의 시간을 가진 char[] 타입 문자열로 확장된다. 참고로 C/C++에서 char 타입은 산술연산이 가능함.

위 예시 코드의 동작은 아래와 같다.

  1. 컴파일 타임(정확히는 매크로가 확장되는 전처리 작업 때)을 기반으로 의사 난수를 생성함. __TIME__ 매크로는 초단위로 값이 바뀌기 때문에 의사 난수값은 매 초마다 갱신된다.

  2. foo에 의미없는 산술연산 수행 (실행 전과 후의 상태가 동일함)

  3. 콘솔에 foo 출력

결과는 아래와 같이 정상적으로 100을 출력하였다.

C:\dev> example.exe
100

그런데 문제가 생겼다.

다형성을 결정짓는 변수 bar가 아래 실행파일에서 찾아볼 수가 없다. 왜 그럴까?

* example.exe!main() 함수를 디스어셈블한 코드

그 이유는 컴파일러의 코드 최적화(Release 빌드는 최대 최적화 /O2가 기본값) 과정에서 bar는 없어도 무방한 변수이므로 삭제되었기 때문이다.

__TIME__ 매크로를 사용해 매 초마다 파일 해시가 다른 실행파일을 생성하고 싶었는데, 다른 방법이 없을까?

// RandomSeed 함수 출처: Conti V3.0 랜섬웨어 소스코드
constexpr int RandomSeed(void)
{
	return '0' * -40271 + // offset accounting for digits' ANSI offsets
		__TIME__[7] * 1 +
		__TIME__[6] * 10 +
		__TIME__[4] * 60 +
		__TIME__[3] * 600 +
		__TIME__[1] * 3600 +
		__TIME__[0] * 36000;
};

int main(void)
{
	int foo = 100;
	volatile int bar = RandomSeed();
	foo = foo + bar - bar;
	printf("%d\n", foo);
}

이 문제는 volatile <TYPE> 키워드를 사용하면 간단하게 해결할 수 있다.

컴파일러의 코드 최적화는 컴파일 대상이 되는 단일 프로그램 내에서 수행되는 것이다. 만약, 외부에서 이 프로그램의 변수에 접근하려는데, 최적화되어 사라진 상태라면 난감할 것이다. 이런 문제를 완화시켜줄 목적으로 volatile 키워드로 선언된 변수는 코드 최적화에서 제외된다. 실행 전과 후의 상태가 동일한 코드는 컴파일 타임에 최적화되어 사라지기 쉬운데, 이런 트릭을 사용하면 어느정도 완화가 가능하다.

다형성 코드는 소스코드 뿐만 아니라 패커, 컴파일러, 어셈블러 등등 다양한 수준에서 구현할 수 있다. 소스코드가 아닌 다른 수준에서 다형성 코드를 생성하고 싶다면 이미 만들어진게 인터넷에 공개되어 있으니 참고하여 아이디어를 얻을 수 있다.

PreviousMSIExecNext후속 공격의 진화

Last updated 2 years ago

🐍