- 프레임워크: Claude Agent SDK (Anthropic)
- 프로토콜: MCP (Model Context Protocol)
- 목적: 실제 APT 그룹의 공격무기를 분석하고, 사용자 인프라로 C2를 교체하여 위협 시뮬레이션용 공격무기를 재빌드하는 자동화 파이프라인
목차
- 시스템 개요 및 목표
- 전체 파이프라인 흐름
- 에이전트 팀 구성 (6명)
- MCP 서버 설계
- 핵심 기술 과제 상세
- 단계별 구축 로드맵 (Step-by-Step)
- 프롬프트 에셋 설계
- 데이터 스키마 (JSON 구조 정의)
- 개발 환경 세팅 가이드
- 검증 및 테스트 계획
- 리스크 및 대응 방안
- 악성코드 분석 팀 / 레드팀과의 연동
1. 시스템 개요 및 목표
미션
실제 해킹 그룹(APT)이 사용한 공격무기(악성코드)를 역공학 분석하여 핵심 기능을 추출하고, 원본의 안티디버깅/난독화/통신 방식은 그대로 유지하면서 C2 인프라만 사용자의 테스트 환경으로 교체한 위협 시뮬레이션용 공격무기를 자동으로 재빌드하여 실행파일 + 설명서를 산출하는 시스템.
핵심 가치
이 시스템이 존재해야 하는 이유:
- 실제 APT의 TTP(전술/기술/절차)를 그대로 재현한 위협 시뮬레이션 가능
- 수작업 역공학 → 재빌드에 수일~수주 걸리던 작업을 자동화
- 블루팀이 실제 위협과 동일한 행위를 탐지/대응 훈련할 수 있는 도구 생산
- 기존 도구(Cobalt Strike 등)와 달리 실제 APT 무기의 고유 특성을 보존
입력과 출력
입력:
- 악성코드 샘플 파일 (PE, ELF, DLL, 스크립트 등)
- 또는 SHA256 해시 (VirusTotal에서 자동 다운로드)
- 사용자 C2 인프라 정보 (IP, 도메인, 포트, 프로토콜)
- 선택: 커스텀 설정 (페이로드 변경, 추가 기능 등)
출력:
- 재빌드된 공격무기 실행파일 (또는 스크립트)
- 상세 설명서 (.txt) – 원본 분석 결과, 변경사항, 사용법
- 분석 결과 JSON (다른 시스템 연동용)
핵심 원칙
- 기능 보존 (Feature Preservation): 원본의 안티디버깅, 난독화, 통신 프로토콜 방식을 최대한 보존
- C2 완전 교체 (C2 Replacement): 원본 해킹 그룹의 모든 네트워크 통신을 사용자 인프라로 100% 교체
- 빌드 무결성 (Build Integrity): 재빌드된 무기가 원본과 동일한 방식으로 실행됨을 보장
- 안전 운용 (Safe Operation): 테스트 환경 외부로의 통신 불가능하도록 설계
2. 전체 파이프라인 흐름
6단계 파이프라인
사용자 입력
(샘플 파일 또는 SHA256 해시 + 사용자 C2 인프라 정보)
|
v
=== STAGE 1: 샘플 확보 ===
Sample Acquirer
- 파일 직접 수신 또는 VT에서 해시 기반 다운로드
- 파일 유형 판별 (PE/ELF/DLL/스크립트/패킹 여부)
- 기본 메타데이터 추출
-> SampleInfo
|
v
=== STAGE 2: 심층 역공학 분석 ===
Weapon Analyst (핵심)
- Ghidra 디컴파일 기반 전체 분석
- 핵심 기능 추출:
(a) 안티디버깅 기법 식별 및 코드 추출
(b) 코드 난객화 방식 식별 및 패턴 추출
(c) C2 통신 프로토콜/주소/포트/암호화 방식 식별
(d) 명령 체계(Command Handler) 구조 분석
(e) 지속성/권한상승/탈취 로직 식별
- 각 기능의 코드 블록을 구조화하여 추출
-> WeaponAnalysisResult
|
v
=== STAGE 3: C2 교체 설계 ===
C2 Replacer
- 원본 C2 주소/도메인/포트 전수 식별
- 사용자 인프라 정보로 교체 매핑 테이블 생성
- 통신 프로토콜 호환성 검증
- 암호화 키/인증서 교체 필요 여부 판단
- 하드코딩된 문자열, 설정 블록, 레지스트리 값 등 모든 참조점 식별
-> C2ReplacementPlan
|
v
=== STAGE 4: 소스코드 재구성 ===
Code Reconstructor (핵심)
- 분석된 기능별 코드 블록을 재구성하여 컴파일 가능한 소스코드 생성
- 바이너리인 경우:
· 디컴파일 C 코드 기반으로 컴파일 가능한 C/C++ 소스 재구성
· 원본과 동일한 안티디버깅 로직 구현
· 원본과 동일한 난객화 패턴 적용
· C2 주소/설정을 사용자 인프라로 교체
- 스크립트인 경우:
· 원본 스크립트 복사 후 C2 참조점만 교체
· 난객화 레이어 유지 (디코딩 → 교체 → 재인코딩)
· 추가 난객화가 깨진 경우 동일 방식으로 재적용
-> ReconstructedSource
|
v
=== STAGE 5: 빌드 및 검증 ===
Build Engineer
- 바이너리: 적절한 컴파일러로 빌드 (MSVC, GCC, MinGW 등)
- 스크립트: 패키징 또는 그대로 출력
- 빌드 후 기능 검증:
· 안티디버깅 로직 정상 동작 확인
· C2 통신 대상이 사용자 인프라인지 확인
· 원본과의 행위 유사도 비교
- 빌드 실패 시 Code Reconstructor에 피드백 → 재시도
-> BuildResult
|
v
=== STAGE 6: 문서화 및 산출 ===
Documentation Writer
- 원본 악성코드 분석 요약
- 핵심 기능별 상세 설명
- 변경사항 목록 (원본 vs 재빌드)
- 사용법 가이드 (실행 방법, 예상 행위)
- 주의사항 및 탐지 시그니처
-> 설명서(.txt) + 실행파일(또는 스크립트)
3. 에이전트 팀 구성 (6명)
에이전트 #1: Build Commander (빌드 지휘관)
역할: 전체 공격무기 빌드 파이프라인 총괄 모델: claude-opus-4-6
담당 업무:
- 입력 접수 (샘플 + 사용자 C2 정보) 및 파이프라인 시작
- 각 에이전트에게 단계별 태스크 할당
- 에이전트 간 데이터 흐름 관리 및 품질 검증
- 빌드 실패 시 재시도/롤백 판단
- 최종 산출물(실행파일 + 설명서) 통합 및 전달
도구 (Tools):
dispatch_task: 에이전트 태스크 위임validate_output: 각 단계 출력 검증merge_results: 결과 병합check_safety: 안전성 검증 (원본 C2로 통신 불가 확인)
판단 기준:
- Stage 2(분석) 완료 후 재빌드 가능 여부 판단
- 디컴파일 품질이 너무 낮으면 “부분 재빌드” 또는 “바이너리 패칭” 전략 전환
- 패킹된 바이너리면 언패킹 우선 시도
- Stage 4(소스 재구성) 실패 시 → 바이너리 패칭 폴백 전략
- 최종 산출물에서 원본 C2 잔존 여부 반드시 검증
에이전트 #2: Sample Acquirer (샘플 확보 에이전트)
역할: 악성코드 샘플 확보 및 기본 분류 모델: claude-sonnet-4-6
담당 업무:
- 사용자 제공 파일 수신 및 검증
- SHA256 해시 입력 시 VirusTotal API로 샘플 다운로드
- 파일 유형 판별:
- 바이너리: PE (x86/x64), ELF, MachO, DLL
- 스크립트: PowerShell, Python, JavaScript, VBScript, Batch
- 문서형: HWP/DOC 매크로, PDF 내장 스크립트
- 패킹 여부: UPX, Themida, VMProtect 등 패커 탐지
- 기본 메타데이터 추출 (해시, 크기, 헤더, 임포트 등)
- 해킹 그룹 어트리뷰션 정보 수집 (VT 태그, YARA 매칭)
도구 (Tools):
vt_download: VirusTotal API로 샘플 다운로드vt_report: VirusTotal 분석 리포트 조회file_identify: 파일 유형/아키텍처 판별parse_header: PE/ELF 헤더 파싱detect_packer: 패커/프로텍터 탐지hash_file: 해시 생성 (MD5/SHA1/SHA256)yara_scan: YARA 룰 매칭 (APT 그룹 시그니처)unpack_sample: 패커 자동 언패킹 시도 (UPX 등)
출력 스키마: SampleInfo
에이전트 #3: Weapon Analyst (무기 분석가) ★ 핵심 에이전트
역할: 악성코드 심층 역공학 분석 및 핵심 기능 추출 모델: claude-opus-4-6
담당 업무:
- Ghidra 디컴파일 기반 전체 코드 분석
- 5대 핵심 기능 추출:
(A) 안티디버깅 기법 식별 및 코드 추출
- IsDebuggerPresent, NtQueryInformationProcess 등 API 호출
- 타이밍 체크 (RDTSC, GetTickCount)
- 하드웨어 브레이크포인트 탐지
- VM/샌드박스 탐지 (CPUID, MAC 주소, 프로세스 목록)
- 해당 코드 블록을 추출하여 구조화
(B) 코드 난객화 방식 식별 및 패턴 추출
- 문자열 암호화 방식 (XOR, AES, RC4, 커스텀)
- 제어 흐름 난객화 (플래트닝, 불투명 술어)
- API 해싱 (API 이름을 해시로 resolve)
- 동적 API 로딩 (LoadLibrary + GetProcAddress 패턴)
- 각 난객화 기법의 키/상수/알고리즘 추출
© C2 통신 프로토콜 완전 분석
- C2 서버 주소/도메인/포트 식별 (하드코딩/설정파일/레지스트리)
- 통신 프로토콜 (HTTP/HTTPS/DNS/TCP Raw/Named Pipe 등)
- 요청/응답 포맷 (헤더, 바디, 인코딩)
- 암호화/인증 방식 (TLS, 커스텀 암호화, 인증서 피닝)
- 비콘 주기/지터 설정
- 폴백 C2 / DGA(Domain Generation Algorithm) 여부
(D) 명령 체계(Command Handler) 분석
- 지원 명령어 목록 (파일 다운로드/업로드, 셸 실행, 스크린샷 등)
- 명령 파싱 로직
- 응답 포맷
(E) 기타 핵심 기능
- 지속성 메커니즘
- 권한 상승 기법
- 데이터 수집/탈취 로직
- 자가 삭제/업데이트 기능
스크립트형 악성코드의 경우:
- 난객화 레이어 순차적 디코딩
- 각 레이어별 난객화 기법 기록
- 최종 디코딩된 평문 코드에서 위 (A)~(E) 분석
도구 (Tools):
ghidra_decompile: 함수 디컴파일ghidra_get_xrefs: 교차 참조 조회ghidra_get_function: 주소 기반 함수 조회ghidra_list_functions: 전체 함수 목록ghidra_get_imports: 임포트 API 목록ghidra_get_strings: 문자열 목록ghidra_get_bytes: 원시 바이트 조회ghidra_get_data: 데이터 섹션 조회script_deobfuscate: 스크립트 난객화 해제 도구extract_config: 악성코드 설정(Config) 자동 추출crypto_identify: 암호화 알고리즘 식별
능동적 탐색 로직:
- Entry Point → main 함수 → 초기화 루틴 추적
- 안티디버깅 체크 함수 식별 (보통 초기에 실행)
- C2 초기화 함수 추적 → 통신 루틴 전체 분석
- 문자열 복호화 함수 식별 → 모든 암호화된 문자열 해독
- Command Handler 디스패치 테이블 분석
- 각 기능별 코드 블록을 "추출 가능한 단위"로 구조화
출력 스키마: WeaponAnalysisResult
에이전트 #4: C2 Replacer (C2 교체 전문가)
역할: 원본 C2 통신 대상을 사용자 인프라로 완전 교체하는 설계 모델: claude-opus-4-6
담당 업무:
-
원본에서 식별된 모든 C2 참조점을 전수 목록화:
- 하드코딩된 IP/도메인 문자열
- 설정 블록(Config Block) 내 C2 정보
- 레지스트리/파일에서 읽어오는 C2 정보
- DGA 알고리즘의 시드/상수
- DNS 쿼리 대상 도메인
- 인증서/키 데이터
- User-Agent, HTTP 헤더 내 식별자
-
사용자 인프라 정보와 1:1 매핑 테이블 생성:
- 원본 C2 IP 123.45.67.89 → 사용자 C2 IP 10.0.0.100
- 원본 도메인 evil.com → 사용자 도메인 test.local
- 원본 포트 443 → 사용자 포트 8443 (또는 유지)
- 원본 암호화 키 → 사용자 키 (또는 유지)
-
교체 방식 결정:
- 소스코드 수준 교체 (소스 재구성 시)
- 바이너리 패칭 (소스 재구성 불가 시)
- 스크립트 텍스트 치환 (스크립트형)
- 설정 블록(Config) 패칭 (Config 기반 악성코드)
-
통신 호환성 검증:
- 사용자 C2 서버가 원본 프로토콜을 지원하는지 확인
- 필요시 프로토콜 어댑터 코드 생성 제안
도구 (Tools):
map_c2_references: C2 참조점 전수 식별create_replacement_table: 교체 매핑 테이블 생성validate_compatibility: 프로토콜 호환성 검증patch_binary_c2: 바이너리 수준 C2 패칭 (폴백)patch_config_block: 설정 블록 패칭
출력 스키마: C2ReplacementPlan
에이전트 #5: Code Reconstructor (코드 재구성 전문가) ★ 핵심 에이전트
역할: 분석 결과를 바탕으로 컴파일 가능한 소스코드 재구성 모델: claude-opus-4-6
담당 업무:
바이너리 악성코드의 경우
-
디컴파일된 C 의사코드를 컴파일 가능한 C/C++ 소스로 재구성
-
재구성 순서:
- 프로젝트 스캐폴딩 (헤더, 메인, 모듈 분리)
- 안티디버깅 모듈 재구성
- Weapon Analyst가 추출한 안티디버깅 코드 블록을 컴파일 가능하게 변환
- API 호출, 상수, 로직 원본 동일 유지
- 난객화 모듈 재구성
- 문자열 암호화 함수 재구현 (동일 알고리즘, 동일 키)
- API 해싱 함수 재구현 (동일 해시 알고리즘)
- 동적 API 로딩 패턴 유지
- C2 통신 모듈 재구성
- 원본 통신 프로토콜 동일 구현
- C2ReplacementPlan에 따라 주소/도메인/포트 교체
- 암호화/인코딩 동일 유지
- Command Handler 재구성
- 원본 명령 체계 동일 구현
- 기타 기능 모듈 재구성
- 지속성, 권한상승, 데이터 수집 등
-
컴파일러/빌드 환경 결정:
- Windows PE → MSVC 또는 MinGW
- Linux ELF → GCC
- DLL → 적절한 엔트리포인트 및 내보내기 함수
스크립트 악성코드의 경우
- 원본 스크립트 복사
- 난객화 레이어 처리:
- 외부 난객화 레이어 디코딩 (인코딩된 문자열, base64 등)
- C2 참조점 식별 및 교체
- 동일한 난객화 방식으로 재인코딩
- 예: base64 인코딩 → 디코딩 → C2 교체 → 다시 base64 인코딩
- 예: XOR 난객화 → 복호화 → C2 교체 → 동일 키로 재암호화
- PowerShell: Invoke-Obfuscation 스타일 재난객화
- JavaScript: eval/unescape 체인 재구성
- VBScript: Chr() 연결 패턴 재구성
- Python: exec/compile 난객화 재적용
도구 (Tools):
generate_source: 분석 결과 → 컴파일 가능 소스 생성apply_anti_debug: 안티디버깅 코드 삽입apply_obfuscation: 난객화 적용 (원본 동일 방식)replace_c2_in_source: 소스 내 C2 참조 교체script_reobfuscate: 스크립트 재난객화validate_source: 소스 코드 문법/구조 검증generate_build_config: 빌드 설정 파일 생성 (Makefile, CMake 등)
폴백 전략 (소스 재구성 실패 시):
- 바이너리 패칭: 원본 바이너리에서 C2 문자열만 직접 패치
- 동일 길이 문자열 교체 (패딩 처리)
- 암호화된 C2의 경우 → 동일 키로 사용자 C2 암호화 후 패치
- 설정 블록(Config) 오프셋 직접 패치
- 이 경우 안티디버깅/난객화는 원본 그대로 유지됨 (장점)
출력 스키마: ReconstructedSource
에이전트 #6: Build Engineer (빌드 엔지니어)
역할: 소스코드 컴파일/빌드 및 최종 산출물 생성 모델: claude-sonnet-4-6
담당 업무:
빌드
-
바이너리 빌드:
- 적절한 컴파일러 선택 및 빌드 실행
- 컴파일 에러 시 Code Reconstructor에 피드백 → 수정 → 재빌드
- 최대 3회 반복
- 링커 설정 (임포트 라이브러리, 섹션 속성)
- 빌드 최적화 옵션 (원본과 유사한 바이너리 크기 유지)
-
스크립트 패키징:
- 스크립트 파일 최종 정리
- 필요시 실행 래퍼 생성
검증
-
C2 교체 완전성 검증:
- 빌드된 바이너리/스크립트에서 원본 C2 문자열 잔존 검색 (핵심!)
- strings 명령, 바이너리 패턴 검색으로 원본 IP/도메인 누락 없는지 확인
- 이것이 통과해야만 최종 산출물로 인정
-
기능 검증 (샌드박스 내):
- 안티디버깅 로직 존재 확인
- C2 연결 시도 대상이 사용자 인프라인지 네트워크 캡처로 확인
- 원본 대비 행위 유사도 평가
-
빌드 아티팩트 정리 (중간 파일 삭제)
문서화
- 설명서(.txt) 생성:
- 원본 악성코드 개요 (해킹 그룹, 유형, 타겟)
- 핵심 기능 요약 (안티디버깅, 난객화, C2, 명령 체계)
- 변경사항 상세 (무엇이 교체되었는지)
- 사용법 (실행 방법, 필요 환경, 예상 행위)
- C2 통신 프로토콜 상세 (블루팀 훈련 참고용)
- 탐지 시그니처 (YARA 룰, 네트워크 시그니처)
- 주의사항 (테스트 환경에서만 사용, 법적 고지)
도구 (Tools):
compile_source: 소스 코드 컴파일 (MSVC/GCC/MinGW)verify_no_original_c2: 원본 C2 잔존 검사 (필수!)sandbox_test: 샌드박스 내 동적 행위 테스트network_capture: 네트워크 캡처로 통신 대상 확인generate_documentation: 설명서 생성generate_yara: 탐지용 YARA 룰 생성package_output: 최종 산출물 패키징
출력 스키마: FinalWeaponPackage
4. MCP 서버 설계
총 5개의 MCP 서버를 구축한다.
MCP 서버 #1: sample-mcp (샘플 확보 서버) – 인프로세스 MCP
전송 방식: 인프로세스 (create_sdk_mcp_server)
도구 목록:
vt_download: VirusTotal API v3 해시 기반 샘플 다운로드vt_report: VirusTotal 분석 리포트 조회file_identify: magic bytes 기반 파일 유형 판별parse_pe_header: PE 헤더 파싱 (pefile)parse_elf_header: ELF 헤더 파싱 (pyelftools)detect_packer: 패커/프로텍터 탐지 (엔트로피 + 시그니처)hash_file: MD5/SHA1/SHA256/ssdeep 해시 생성yara_scan: YARA 룰 매칭 (APT 그룹 시그니처)unpack_upx: UPX 자동 언패킹extract_strings: 문자열 추출 (ASCII/Unicode)
의존 라이브러리:
- vt-py (VirusTotal API), pefile, pyelftools, yara-python, python-magic
MCP 서버 #2: ghidra-mcp (Ghidra 역공학 서버) – 외부 MCP
전송 방식: stdio 참고: 악성코드 분석 팀의 ghidra-mcp 재사용
도구 목록:
ghidra_headless_analyze: Ghidra Headless 바이너리 분석 실행ghidra_decompile: 함수 디컴파일ghidra_get_function: 주소/이름 기반 함수 조회ghidra_list_functions: 전체 함수 목록ghidra_get_xrefs: 교차 참조 조회ghidra_get_imports: 임포트 테이블ghidra_get_exports: 익스포트 테이블ghidra_list_strings: 문자열 목록ghidra_get_bytes: 원시 바이트 조회ghidra_get_segments: 섹션/세그먼트 정보ghidra_search_memory: 메모리 패턴 검색
MCP 서버 #3: analysis-mcp (분석 보조 서버) – 인프로세스 MCP
전송 방식: 인프로세스
도구 목록:
crypto_identify: 암호화 알고리즘 식별 (상수/S-Box 매칭)extract_config: 악성코드 Config 블록 자동 추출script_deobfuscate: 스크립트 단계별 디코딩api_hash_resolve: API 해시값 → 실제 API 이름 해석string_decrypt: 암호화된 문자열 복호화 (키/알고리즘 지정)pattern_match: 바이너리 패턴 검색 (C2, 키, 매직바이트)c2_protocol_fingerprint: C2 통신 프로토콜 핑거프린팅
의존 라이브러리:
- yara-python, pefile, capstone (디스어셈블러), unicorn (에뮬레이션, 선택)
MCP 서버 #4: build-mcp (빌드 서버) – 외부 MCP
전송 방식: stdio (컴파일러 프로세스와 통신, 격리 환경)
도구 목록:
compile_c: C/C++ 소스 컴파일 (GCC/MinGW)compile_msvc: MSVC 컴파일 (Wine+MSVC 또는 Windows 빌드 서버)compile_dll: DLL 빌드link_binary: 링커 실행 (라이브러리 연결)script_package: 스크립트 패키징obfuscate_source: 소스 수준 난객화 적용reobfuscate_script: 스크립트 재난객화patch_binary: 바이너리 직접 패칭 (폴백)verify_no_original_c2: 빌드 결과에서 원본 C2 잔존 검색sign_binary: 코드 서명 (선택)
안전 장치:
- 빌드 환경은 격리된 컨테이너/VM 내에서만 실행
- 빌드 결과물의 네트워크 접근 차단
- 원본 C2 잔존 검사 통과 필수
MCP 서버 #5: verification-mcp (검증 서버) – 외부 MCP
전송 방식: stdio (샌드박스 환경)
도구 목록:
sandbox_execute: 샌드박스 내 바이너리/스크립트 실행network_capture: 실행 중 네트워크 트래픽 캡처verify_c2_target: 캡처된 트래픽에서 C2 대상 검증behavior_compare: 원본 vs 재빌드 행위 유사도 비교antidebug_verify: 안티디버깅 로직 존재 확인strings_search: 빌드 결과물에서 문자열 검색entropy_check: 섹션별 엔트로피 비교 (난객화 유지 확인)
의존 도구:
- 샌드박스: Docker 컨테이너 또는 경량 VM
- 네트워크: tcpdump/tshark
- 에뮬레이션: QEMU (선택)
5. 핵심 기술 과제 상세
이 시스템의 기술적 난이도가 높은 부분을 상세히 다룬다.
5.1 과제: 디컴파일 코드 → 컴파일 가능 소스 변환
문제: Ghidra 디컴파일 출력은 “읽기용” C 의사코드이며 바로 컴파일되지 않는다. undefined4, undefined8 같은 타입, Ghidra 특수 매크로, 누락된 헤더 등이 있다.
해결 전략:
-
타입 매핑 테이블
undefined4→uint32_t/DWORDundefined8→uint64_t/QWORDundefined→uint8_t/BYTElonglong→int64_t- Ghidra 구조체 → 수동 typedef 생성
-
헤더/인클루드 자동 생성
- 임포트 API 분석 → 필요한 Windows/Linux 헤더 결정
#include <windows.h>,<winsock2.h>,<wininet.h>등
-
Ghidra 특수 구문 변환
CONCAT44(a,b)→((uint64_t)a << 32) | bSUB41(a,0)→(uint8_t)(a)(code *)0x0→NULL또는 함수 포인터 캐스팅
-
함수 시그니처 정리
- 호출 규약 명시 (
__stdcall,__cdecl) - 파라미터 타입 정리
- 호출 규약 명시 (
-
전역 변수/데이터 섹션 재구성
- DAT_ 변수들의 실제 값 채움
- 문자열 데이터 초기화
Code Reconstructor 에이전트의 프롬프트에 이 변환 규칙을 전부 주입한다.
5.2 과제: 암호화된 C2 교체
문제: 많은 APT 악성코드는 C2 주소를 암호화하여 저장한다. 단순 문자열 교체로는 안 되고, 동일한 암호화 알고리즘으로 새 C2 주소를 암호화하여 교체해야 한다.
해결 전략:
-
Weapon Analyst가 문자열 복호화 함수를 완전 분석
- 알고리즘 식별 (XOR, RC4, AES, 커스텀)
- 키/IV/상수 추출
-
C2 Replacer가 교체 계획 수립
- 평문 원본 C2 → 평문 사용자 C2 매핑
- 동일 알고리즘 + 동일 키로 사용자 C2 암호화
-
Code Reconstructor가 적용
- 소스 재구성 시: 초기화 데이터에 암호화된 사용자 C2 삽입
- 바이너리 패칭 시: 암호화된 바이트열 직접 교체 (동일 길이 확인!)
-
길이 불일치 처리
- 사용자 C2가 원본보다 짧으면: 널 패딩
- 사용자 C2가 원본보다 길면: 경고 후 축약 또는 바이너리 확장
5.3 과제: 스크립트 난객화 레이어 유지
문제: PowerShell, JS 등 스크립트 악성코드는 다중 난객화 레이어로 감싸져 있다. C2를 교체하려면 일단 풀어야 하는데, 풀고 나서 다시 동일하게 감싸야 한다.
해결 전략:
양파 껍질(Onion Peeling) 접근법:
-
난객화 레이어 분석 (바깥 → 안쪽)
Layer 3 (가장 바깥): base64 인코딩 Layer 2: XOR 암호화 (키: 0x37) Layer 1: 변수명 난객화 + 문자열 분할 -
순차적 디코딩 (바깥 → 안쪽)
- 각 레이어의 디코딩 방법과 파라미터를 기록
-
최내부 평문에서 C2 교체
-
역순으로 재인코딩 (안쪽 → 바깥)
- Layer 1: 동일한 변수명 패턴 + 문자열 분할 방식 적용
- Layer 2: 동일한 XOR 키(0x37)로 재암호화
- Layer 3: base64 재인코딩
이 과정을 script_deobfuscate + script_reobfuscate 도구가 처리하며, Weapon Analyst가 각 레이어의 상세 정보를 제공한다.
5.4 과제: 바이너리 패칭 폴백
문제: 복잡한 악성코드는 소스 재구성이 불가능할 수 있다 (VMProtect 등). 이 경우 원본 바이너리를 직접 패칭해야 한다.
해결 전략:
-
Config 기반 패칭 (선호)
- 많은 RAT/백도어는 Config 블록에 C2 정보를 저장
- Config 블록의 오프셋과 구조를 분석
- 해당 오프셋의 바이트를 직접 교체
- 체크섬이 있으면 재계산
-
문자열 패칭
- 평문 C2 문자열의 파일 오프셋 확인
- 동일 길이로 교체 (나머지 널 패딩)
- 여러 참조점 모두 교체
-
암호화된 데이터 패칭
- 복호화 알고리즘/키를 이용해 새 C2를 암호화
- 암호화된 바이트열로 해당 오프셋 교체
장점: 안티디버깅, 난객화가 원본 100% 그대로 유지 단점: 유연성 낮음 (C2 외 변경 어려움)
6. 단계별 구축 로드맵 (Step-by-Step)
전체 기간: 약 14~16주 (1인 개발 기준) 요구사항: 악성코드 분석 팀 + 코드 생성/빌드 역량 필요로 가장 복잡한 팀.
PHASE 1: 기반 인프라 및 빌드 환경 구축 (1~2주차)
Step 1.1 – 프로젝트 초기화 및 빌드 툴체인 준비
- Python 프로젝트 구조 생성 (위 디렉토리 구조 참조)
- 컴파일러 환경 준비:
- GCC / MinGW-w64 (크로스 컴파일)
- MSVC Build Tools (Wine 환경 또는 Windows 빌드 서버)
- Docker 기반 격리 빌드 환경 구성
- Ghidra Headless 설치 및 검증
Step 1.2 – VirusTotal API 연동
- VT API v3 래퍼 작성
- 해시 기반 다운로드 테스트
- 리포트 조회 테스트
- API 키 관리 및 Rate Limit 처리
Step 1.3 – 샌드박스 검증 환경 구축
- Docker 기반 경량 분석 샌드박스
- tcpdump/tshark 네트워크 캡처 설정
- 격리 네트워크 구성 (외부 통신 차단)
PHASE 2: 핵심 MCP 서버 개발 (3~6주차)
Step 2.1 – sample-mcp 서버 구현 (0.5주)
- VT 다운로드/리포트 도구
- 파일 식별/헤더 파싱 도구
- 패커 탐지 및 UPX 언패킹
- YARA APT 시그니처 매칭
Step 2.2 – ghidra-mcp 서버 (악성코드 분석 팀 것 재사용 또는 확장) (0.5주)
- 기존 도구 + search_memory 도구 추가
- Config 추출 보조 기능 추가
Step 2.3 – analysis-mcp 서버 구현 (1.5주)
- crypto_identify: AES/RC4/XOR/커스텀 상수 매칭
- extract_config: 알려진 RAT Config 패턴 추출
- script_deobfuscate: PowerShell/JS/VBS 다단계 디코딩
- api_hash_resolve: 알려진 API 해싱 알고리즘 DB
- string_decrypt: 키/알고리즘 지정 문자열 복호화
- c2_protocol_fingerprint: HTTP/DNS/TCP 패턴 식별
Step 2.4 – build-mcp 서버 구현 (1.5주, 핵심)
- GCC/MinGW 컴파일 래퍼 (에러 파싱 포함)
- MSVC 컴파일 래퍼 (크로스 환경)
- DLL 빌드 지원
- 소스 수준 난객화 적용 도구
- 스크립트 재난객화 도구 (PS, JS, VBS 각각)
- 바이너리 패칭 도구 (오프셋 기반)
- 원본 C2 잔존 검사 도구 (문자열+패턴)
Step 2.5 – verification-mcp 서버 구현 (1주)
- Docker 샌드박스 실행 래퍼
- 네트워크 캡처 및 분석
- C2 대상 검증 로직
- 행위 비교 로직
- 엔트로피/문자열 비교
PHASE 3: 에이전트 개발 및 프롬프트 엔지니어링 (7~11주차)
Step 3.1 – Sample Acquirer 에이전트 (0.5주)
- VT 다운로드 + 파일 식별 파이프라인
- 패커 탐지 → 언패킹 자동화
- APT 그룹 어트리뷰션 프롬프트
Step 3.2 – Weapon Analyst 에이전트 (3주, 최핵심)
- 5대 핵심 기능 추출 프롬프트 설계
- 능동적 탐색: 엔트리포인트 → 초기화 → C2 → 명령 체계
- 안티디버깅 코드 블록 구조화 추출 프롬프트
- 난객화 기법 식별 및 파라미터 추출 프롬프트
- C2 통신 완전 분석 프롬프트
- 스크립트 난객화 레이어 분석 프롬프트
- 환각 방지: 모든 판단에 코드 주소/근거 필수
- 테스트: 알려진 APT 샘플로 추출 품질 검증
Step 3.3 – C2 Replacer 에이전트 (1주)
- C2 참조점 전수 식별 프롬프트
- 교체 매핑 테이블 생성 로직
- 암호화된 C2 교체 전략 프롬프트
- 호환성 검증 로직
Step 3.4 – Code Reconstructor 에이전트 (2주, 핵심)
- Ghidra 타입 → C 타입 변환 규칙 프롬프트 주입
- 모듈별 소스 재구성 프롬프트
- 스크립트 재난객화 프롬프트
- 바이너리 패칭 폴백 로직
- 컴파일 에러 자동 수정 루프
Step 3.5 – Build Engineer 에이전트 (1주)
- 빌드 → 검증 → 문서화 파이프라인
- 원본 C2 잔존 검사 필수 게이트
- 설명서 생성 프롬프트
- 빌드 실패 → 피드백 → 재시도 루프
Step 3.6 – Build Commander 에이전트 (0.5주)
- 전체 6단계 오케스트레이션
- 폴백 전략 판단 로직 (소스 재구성 vs 바이너리 패칭)
- 품질 게이트 및 최종 검증
PHASE 4: 통합 및 검증 (12~14주차)
Step 4.1 – End-to-End 통합 테스트
- 1단계: 단순 스크립트 악성코드 (PowerShell 다운로더)
- 2단계: 단순 PE 악성코드 (기본 C2 통신)
- 3단계: 난객화된 스크립트 (다중 레이어)
- 4단계: 복합 PE 악성코드 (안티디버깅 + 암호화 C2)
- 5단계: 알려진 APT 샘플 (실전 테스트)
Step 4.2 – 폴백 전략 검증
- 소스 재구성 불가 케이스 → 바이너리 패칭 자동 전환 테스트
- Config 기반 악성코드 → Config 패칭 테스트
- 패킹된 악성코드 → 언패킹 → 분석 → 재빌드 테스트
Step 4.3 – 최적화
- 토큰 사용량 최적화
- 빌드 시간 최적화
- 비용 추적 및 제한
PHASE 5: 문서화 및 마무리 (15~16주차)
- Step 5.1: 사용 매뉴얼 작성
- Step 5.2: 지원 악성코드 유형별 가이드
- Step 5.3: 트러블슈팅 가이드
7. 프롬프트 에셋 설계
7.1 Weapon Analyst 시스템 프롬프트 (핵심 – 초안)
당신은 15년 경력의 시니어 악성코드 역공학 분석가이며,
APT 그룹의 공격무기를 분석하여 핵심 기능을 추출하는 전문가입니다.
## 임무
악성코드를 분석하여 다음 5가지 핵심 기능을 구조화된 형태로 추출하세요.
추출된 정보는 다른 에이전트가 공격무기를 재구성하는 데 직접 사용됩니다.
따라서 "코드 수준"의 구체적인 정보가 필요합니다.
## 추출 대상 5가지
### (A) 안티디버깅 기법
식별할 것:
- 사용된 API (IsDebuggerPresent, NtQueryInformationProcess 등)
- 타이밍 체크 (RDTSC, GetTickCount 차이값 비교)
- 하드웨어 BP 탐지 (DR0-DR7 레지스터 검사)
- VM/샌드박스 탐지 (CPUID, MAC, 프로세스명, 파일 존재 확인)
추출할 것:
- 해당 함수의 전체 디컴파일 코드
- 사용된 상수값/임계값
- 탐지 시 행위 (종료, 루프, 더미 동작)
### (B) 코드 난객화 방식
식별할 것:
- 문자열 암호화: 알고리즘(XOR/RC4/AES/커스텀), 키, IV
- API 해싱: 해시 알고리즘(CRC32/DJB2/커스텀), 시드값
- 동적 API 로딩: LoadLibrary+GetProcAddress 패턴
- 제어 흐름 난객화: 플래트닝, 불투명 술어, 가짜 분기
추출할 것:
- 복호화/해싱 함수의 전체 코드
- 키, 시드, 상수값
- 인코딩된 원본 데이터와 디코딩된 결과 매핑
### (C) C2 통신 [가장 중요]
식별할 것:
- C2 서버: IP/도메인/포트 (평문 또는 암호화 상태 모두)
- 프로토콜: HTTP(S)/DNS/TCP/UDP/Named Pipe/커스텀
- 통신 포맷: 요청/응답 구조, 헤더, 인코딩
- 암호화: TLS/커스텀 암호화/인증서
- 비콘: 주기, 지터, 폴백 로직
- DGA: 알고리즘, 시드, TLD 목록
추출할 것:
- C2 초기화 함수 전체 코드
- 통신 함수 전체 코드
- 하드코딩된 C2 값의 정확한 주소(오프셋)
- 암호화된 경우: 암호화된 바이트열 + 복호화 결과 + 키
### (D) 명령 체계
- 명령 디스패치 함수와 각 명령 핸들러 코드
- 명령 ID/이름 매핑 테이블
### (E) 기타 기능
- 지속성, 권한상승, 데이터 수집 등 (있는 경우만)
## 근거 요구사항
- 모든 식별에 코드 주소와 함수명을 근거로 제시하세요.
- 확실하지 않으면 "추정"으로 표기하세요.
- 실존하지 않는 함수/주소를 만들어내지 마세요.
## 능동적 탐색
- Entry Point부터 시작하여 초기화 → C2 → 명령 핸들러 순으로 추적하세요.
- 필요하면 ghidra_decompile, ghidra_get_xrefs 등을 자유롭게 호출하세요.
- 문자열 복호화 함수를 찾으면 string_decrypt로 모든 암호화 문자열을 해독하세요.
7.2 Code Reconstructor 시스템 프롬프트 (핵심 – 초안)
당신은 시니어 보안 소프트웨어 엔지니어로, Ghidra 디컴파일 결과를
컴파일 가능한 소스코드로 변환하는 전문가입니다.
## 임무
Weapon Analyst가 추출한 핵심 기능 코드를 바탕으로,
원본과 동일하게 동작하면서 C2만 교체된 컴파일 가능 소스를 생성하세요.
## Ghidra → 실제 C/C++ 변환 규칙
타입 변환:
undefined → uint8_t / BYTE
undefined2 → uint16_t / WORD
undefined4 → uint32_t / DWORD
undefined8 → uint64_t / QWORD
byte → uint8_t
ushort → uint16_t
uint → uint32_t
ulong → uint32_t (Windows 32bit)
ulonglong → uint64_t
longlong → int64_t
bool → BOOL (Windows) 또는 int
code * → 함수 포인터 (적절한 시그니처)
void * → LPVOID
매크로 변환:
CONCAT44(a,b) → ((uint64_t)(a) << 32) | (uint32_t)(b)
CONCAT22(a,b) → ((uint32_t)(a) << 16) | (uint16_t)(b)
SUB41(a,0) → (uint8_t)(a)
SUB42(a,0) → (uint16_t)(a)
SEXT14(a) → (int32_t)(int8_t)(a)
ZEXT14(a) → (uint32_t)(uint8_t)(a)
구조:
- Windows API 사용 시 #include <windows.h> 필수
- 네트워크 시 #include <winsock2.h> #include <ws2tcpip.h>
- HTTP 시 #include <wininet.h> 또는 #include <winhttp.h>
- pragma comment(lib, "...") 로 라이브러리 링크
## 재구성 순서
1. 헤더 및 타입 정의
2. 전역 변수 및 데이터 초기화
3. 안티디버깅 모듈 (Analyst 추출 코드 기반)
4. 난객화 모듈 (동일 알고리즘/키)
5. C2 통신 모듈 (C2ReplacementPlan 적용)
6. 명령 핸들러
7. main/DllMain 엔트리포인트
## C2 교체 규칙
- C2ReplacementPlan의 매핑 테이블을 100% 반영하세요.
- 원본 C2 문자열이 소스 어디에도 남아있으면 안 됩니다.
- 암호화된 C2는 동일 키로 사용자 C2를 암호화하여 삽입하세요.
## 스크립트인 경우
- 원본 스크립트를 복사하세요.
- Analyst가 분석한 난객화 레이어 순서대로 디코딩하세요.
- 최내부에서 C2를 교체하세요.
- 역순으로 동일 방식으로 재난객화하세요.
- 난객화가 깨지면 안 됩니다.
7.3 C2 Replacer 시스템 프롬프트 (초안)
당신은 악성코드 C2 인프라 분석 전문가입니다.
원본 악성코드의 모든 C2 통신 참조점을 식별하고,
사용자 인프라로 교체하는 완벽한 계획을 수립하는 것이 임무입니다.
## 핵심 원칙
- "하나도 빠짐없이" 모든 C2 참조점을 찾아야 합니다.
- 원본 해킹 그룹의 인프라로 통신하는 경로가 단 하나라도 남으면 실패입니다.
## 식별 대상 (전수 조사)
1. 하드코딩된 IP/도메인 문자열 (평문)
2. 암호화/인코딩된 IP/도메인 (base64, XOR, RC4, AES 등)
3. 설정 블록(Config Block) 내 C2 필드
4. 레지스트리에서 읽어오는 C2 정보
5. 파일에서 읽어오는 C2 정보
6. DGA 알고리즘의 시드/상수 (DGA 사용 시)
7. DNS 쿼리 대상 도메인 (DNS 터널링 시)
8. 하드코딩된 포트 번호
9. SSL/TLS 인증서 핀닝 값
10. HTTP User-Agent, 커스텀 헤더 내 식별 값
11. 폴백(Fallback) C2 주소
12. 업데이트/다운로드 URL
## 교체 매핑 테이블 형식
각 참조점에 대해:
- 원본 값 (평문)
- 원본 위치 (코드 주소, 변수명, 파일 오프셋)
- 원본 형태 (평문/암호화/인코딩)
- 교체 대상 (사용자 인프라 값)
- 교체 방식 (소스 교체/바이너리 패치/재암호화)
- 주의사항 (길이 제한, 인코딩 호환성 등)
8. 데이터 스키마 (JSON 구조 정의)
8.1 SampleInfo
{
"sample": {
"filename": "string",
"file_type": "PE_x86 | PE_x64 | ELF | DLL | PowerShell | JavaScript | VBScript | Python | Batch | HWP_Macro | DOC_Macro | Unknown",
"hashes": {
"md5": "string",
"sha1": "string",
"sha256": "string",
"ssdeep": "string"
},
"file_size": "number",
"is_packed": "boolean",
"packer_name": "string | null",
"unpacked_available": "boolean"
},
"attribution": {
"apt_group": "string | null (예: APT28, Lazarus, Kimsuky)",
"malware_family": "string | null",
"campaign": "string | null",
"first_seen": "string | null (ISO 8601)",
"vt_detection_rate": "string (예: 45/72)",
"tags": ["string"]
},
"basic_analysis": {
"entry_point": "string (hex) | null",
"architecture": "string",
"compile_timestamp": "string | null",
"imports_summary": ["string (주요 DLL)"],
"suspicious_apis": ["string"],
"strings_of_interest": [
{
"value": "string",
"category": "url | ip | domain | registry | filepath | command",
"encoding": "ascii | unicode | encrypted"
}
]
}
}
8.2 WeaponAnalysisResult
{
"anti_debugging": {
"techniques": [
{
"name": "string (예: IsDebuggerPresent Check)",
"category": "api_check | timing_check | hardware_bp | vm_detect | sandbox_detect",
"function_address": "string (hex)",
"function_name": "string",
"decompiled_code": "string (전체 함수 코드)",
"constants_used": ["string (임계값, 매직 넘버 등)"],
"detection_action": "string (탐지 시 행위: exit/loop/dummy)"
}
]
},
"obfuscation": {
"string_encryption": {
"algorithm": "string (XOR | RC4 | AES | custom)",
"key": "string (hex 또는 평문)",
"iv": "string | null",
"decrypt_function_address": "string (hex)",
"decrypt_function_code": "string (전체 코드)",
"encrypted_strings": [
{
"encrypted_hex": "string",
"decrypted_value": "string",
"address": "string (hex)",
"is_c2_related": "boolean"
}
]
},
"api_hashing": {
"algorithm": "string (CRC32 | DJB2 | custom)",
"seed": "string | null",
"resolve_function_address": "string (hex)",
"resolve_function_code": "string",
"known_hashes": [
{
"hash_value": "string (hex)",
"resolved_api": "string"
}
]
},
"dynamic_api_loading": {
"used": "boolean",
"pattern": "string (LoadLibrary+GetProcAddress 등)"
},
"control_flow": {
"type": "none | flattening | opaque_predicate | custom",
"description": "string"
}
},
"c2_communication": {
"c2_servers": [
{
"type": "primary | fallback | update",
"value": "string (IP/도메인)",
"port": "number",
"protocol": "http | https | dns | tcp_raw | udp | named_pipe | custom",
"storage": "hardcoded | config_block | registry | file | dga",
"encrypted": "boolean",
"encrypted_value_hex": "string | null",
"address_in_binary": "string (hex, 파일 오프셋)",
"address_in_code": "string (hex, 코드 주소)"
}
],
"dga": {
"used": "boolean",
"algorithm_code": "string | null",
"seed": "string | null",
"tld_list": ["string"],
"domains_per_day": "number | null"
},
"protocol_details": {
"init_function_address": "string (hex)",
"init_function_code": "string",
"send_function_address": "string (hex)",
"send_function_code": "string",
"recv_function_address": "string (hex)",
"recv_function_code": "string",
"request_format": "string (HTTP 요청 예시 등)",
"response_format": "string",
"encryption": {
"used": "boolean",
"algorithm": "string | null",
"key": "string | null"
},
"beacon_interval_ms": "number | null",
"jitter_percent": "number | null"
}
},
"command_handler": {
"dispatcher_address": "string (hex)",
"dispatcher_code": "string",
"commands": [
{
"id": "string (명령 ID 또는 코드)",
"name": "string (추정된 명령 이름)",
"description": "string",
"handler_address": "string (hex)",
"handler_code": "string"
}
]
},
"other_capabilities": {
"persistence": [
{
"type": "registry | scheduled_task | service | startup_folder | ...",
"description": "string",
"code_address": "string (hex)"
}
],
"privilege_escalation": [
{
"technique": "string",
"code_address": "string (hex)"
}
],
"data_collection": [
{
"type": "keylog | screenshot | clipboard | credential | file_search",
"description": "string"
}
]
},
"reconstruction_feasibility": {
"recommended_approach": "source_reconstruction | binary_patching | config_patching",
"confidence": "number (0.0-1.0)",
"challenges": ["string"],
"notes": "string"
}
}
8.3 C2ReplacementPlan
{
"user_infrastructure": {
"c2_servers": [
{
"ip": "string",
"domain": "string | null",
"port": "number",
"protocol": "string"
}
],
"encryption_key": "string | null (사용자 지정 키, 없으면 원본 유지)",
"certificate": "string | null"
},
"replacement_mappings": [
{
"id": "string",
"original_value": "string",
"replacement_value": "string",
"location_type": "source_string | binary_offset | config_field | registry | script_text",
"location_detail": "string (주소/오프셋/변수명/줄번호)",
"encoding": "plaintext | encrypted | base64 | hex",
"encryption_details": {
"algorithm": "string | null",
"key": "string | null",
"original_encrypted_hex": "string | null",
"replacement_encrypted_hex": "string | null"
},
"length_original": "number",
"length_replacement": "number",
"length_match": "boolean",
"padding_needed": "boolean",
"notes": "string"
}
],
"compatibility_check": {
"protocol_compatible": "boolean",
"encryption_compatible": "boolean",
"length_issues": ["string"],
"warnings": ["string"]
}
}
8.4 ReconstructedSource
{
"approach": "source_reconstruction | binary_patching | config_patching | script_modification",
"source_files": [
{
"filename": "string",
"language": "c | cpp | powershell | javascript | vbscript | python | batch",
"content": "string (전체 소스 코드)",
"purpose": "string (main/anti_debug/obfuscation/c2/command_handler/...)"
}
],
"build_config": {
"compiler": "gcc | mingw | msvc | none",
"target_arch": "x86 | x64",
"target_os": "windows | linux",
"compile_flags": ["string"],
"link_libraries": ["string"],
"output_type": "exe | dll | script",
"output_filename": "string"
},
"c2_replacement_applied": "boolean",
"original_c2_removed": "boolean",
"obfuscation_maintained": "boolean",
"anti_debug_maintained": "boolean",
"changes_from_original": [
{
"category": "c2_replacement | type_fix | header_add | build_adaptation",
"description": "string"
}
]
}
8.5 FinalWeaponPackage (최종 산출물)
{
"package_metadata": {
"package_id": "string (UUID)",
"created_at": "string (ISO 8601)",
"original_sample_hash": "string (SHA256)",
"apt_group": "string | null",
"malware_family": "string | null",
"approach_used": "source_reconstruction | binary_patching | config_patching | script_modification",
"total_cost_usd": "number"
},
"output_files": {
"weapon": {
"filename": "string",
"type": "exe | dll | ps1 | js | vbs | py | bat",
"sha256": "string",
"size": "number"
},
"documentation": {
"filename": "string (설명서.txt)",
"content_summary": "string"
},
"analysis_json": {
"filename": "string",
"contains": "WeaponAnalysisResult + C2ReplacementPlan"
}
},
"verification": {
"original_c2_absent": "boolean (필수 true)",
"user_c2_present": "boolean (필수 true)",
"anti_debug_functional": "boolean",
"obfuscation_maintained": "boolean",
"sandbox_test_passed": "boolean",
"network_capture_verified": "boolean",
"behavior_similarity_score": "number (0.0-1.0)"
},
"documentation_content": {
"original_analysis_summary": "string",
"key_capabilities": ["string"],
"changes_made": [
{
"what": "string",
"from": "string",
"to": "string"
}
],
"usage_guide": "string (실행 방법, 예상 행위)",
"c2_protocol_info": "string (블루팀 참고용)",
"detection_signatures": {
"yara_rules": ["string"],
"network_signatures": ["string"]
},
"warnings": ["string"]
}
}
9. 개발 환경 세팅 가이드
필수 소프트웨어
- Python 3.10+
- Ghidra 11.x + Java 17+
- GCC / MinGW-w64 (크로스 컴파일용)
- Docker / Docker Compose (격리 빌드/테스트 환경)
- tcpdump / tshark (네트워크 캡처)
Python 패키지 (requirements.txt)
claude-agent-sdk
vt-py # VirusTotal API
pefile
pyelftools
yara-python
python-magic
jsonschema
pyyaml
jinja2
httpx
capstone # 디스어셈블러
pyhidra # Ghidra 브릿지
외부 도구
- ghidra: 역공학
- gcc / x86_64-w64-mingw32-gcc: 크로스 컴파일
- upx: 언패킹
- strings: 문자열 추출
- objdump: 바이너리 분석 보조
환경 변수
ANTHROPIC_API_KEY=sk-ant-...
VT_API_KEY=...
GHIDRA_INSTALL_DIR=/path/to/ghidra
BUILD_SANDBOX_IMAGE=weapon-builder-sandbox:latest
OUTPUT_DIR=/path/to/output
config.yaml
anthropic:
api_key: ${ANTHROPIC_API_KEY}
max_budget_usd: 15.0
agents:
commander:
model: claude-opus-4-6
sample_acquirer:
model: claude-sonnet-4-6
weapon_analyst:
model: claude-opus-4-6
max_exploration_depth: 15
max_functions_to_analyze: 80
c2_replacer:
model: claude-opus-4-6
code_reconstructor:
model: claude-opus-4-6
max_compile_retries: 3
build_engineer:
model: claude-sonnet-4-6
virustotal:
api_key: ${VT_API_KEY}
rate_limit_per_minute: 4
ghidra:
install_dir: ${GHIDRA_INSTALL_DIR}
headless_timeout_seconds: 600
build:
sandbox_image: ${BUILD_SANDBOX_IMAGE}
compilers:
windows_x86: "i686-w64-mingw32-gcc"
windows_x64: "x86_64-w64-mingw32-gcc"
linux_x64: "gcc"
default_flags: ["-O2", "-s"]
verification:
require_c2_absence_check: true
require_sandbox_test: true
network_capture_timeout: 30
10. 검증 및 테스트 계획
10.1 단위 테스트
- vt_download: 알려진 해시로 샘플 다운로드 확인
- ghidra_decompile: 알려진 함수 디컴파일 결과 검증
- crypto_identify: 알려진 암호화 상수 탐지 확인
- compile_c: 간단한 C 코드 컴파일 성공 확인
- verify_no_original_c2: 문자열 잔존 검사 정확도
10.2 에이전트 단독 테스트
- Weapon Analyst: 알려진 APT 샘플에서 5대 기능 추출 품질
- C2 Replacer: C2 참조점 전수 식별 정확도
- Code Reconstructor: 생성된 소스의 컴파일 성공률
- Build Engineer: 빌드 → 검증 파이프라인 안정성
10.3 통합 테스트 (단계별)
1단계 – PowerShell 다운로더:
- 입력: base64 인코딩된 PS1 스크립트 (단순 C2 통신)
- 기대: 디코딩 → C2 교체 → 재인코딩 → 동작 확인
- 평가: 원본 C2 제거 확인, 난객화 유지 확인
2단계 – 단순 PE (HTTP C2):
- 입력: 평문 HTTP C2 통신하는 간단한 PE 악성코드
- 기대: 디컴파일 → 소스 재구성 → 빌드 → C2 교체 확인
- 평가: 빌드 성공, 원본 C2 부재, 기본 동작 유사
3단계 – XOR 난객화 스크립트:
- 입력: 다중 레이어 XOR 난객화된 PowerShell 악성코드
- 기대: 레이어별 디코딩 → C2 교체 → 재인코딩
- 평가: 모든 레이어 복원 확인, 난객화 구조 동일
4단계 – 암호화 C2 PE:
- 입력: RC4로 C2 암호화된 PE 악성코드 + 안티디버깅
- 기대: 복호화 키 추출 → 사용자 C2 재암호화 → 소스 재구성 → 빌드
- 평가: 암호화된 C2 교체 정확성, 안티디버깅 유지
5단계 – 실전 APT 샘플:
- 입력: 공개된 APT 그룹 샘플 (예: APT28 X-Agent, Lazarus 도구)
- 기대: 전체 파이프라인 정상 동작
- 평가: 전문가 수동 검증, 행위 유사도, 재현 가능성
10.4 핵심 검증 항목 (반드시 통과)
- 원본 C2 부재 확인: 빌드 결과물에서 원본 IP/도메인 문자열 검색 → 0건
- 사용자 C2 동작 확인: 네트워크 캡처에서 사용자 C2로만 통신 시도
- 난객화 유지 확인: 원본과 동일한 엔트로피/패턴
- 안티디버깅 유지 확인: 디버거 연결 시 탐지 동작 확인
11. 리스크 및 대응 방안
리스크 1: 디컴파일 품질 부족으로 소스 재구성 불가
원인: 복잡한 난객화, 패커, 컴파일러 최적화
대응:
- 바이너리 패칭 폴백 전략 자동 전환
- Config 패칭 우선 시도 (C2만 교체하면 되므로)
- Commander가 재빌드 가능성 사전 평가
리스크 2: 암호화된 C2 교체 실패
원인: 복호화 키/알고리즘 분석 실패, 길이 불일치
대응:
- 여러 암호화 식별 전략 병행 (상수 매칭, 에뮬레이션)
- 길이 불일치 시 패딩/축약 전략
- 완전 실패 시 수동 개입 안내
리스크 3: 빌드 실패 (컴파일 에러)
원인: Ghidra 타입/매크로 변환 불완전
대응:
- Code Reconstructor ↔ Build Engineer 피드백 루프 (최대 3회)
- 에러 메시지 기반 자동 수정
- 반복 실패 시 바이너리 패칭으로 폴백
리스크 4: 원본 C2 잔존
원인: 암호화된 C2, 설정 블록 내 숨겨진 참조점 누락
대응:
- verify_no_original_c2 필수 게이트 (통과 못하면 출력 불가)
- 다중 검사: 문자열 + 바이너리 패턴 + 네트워크 캡처
- C2 Replacer의 “전수 조사” 프롬프트 강화
리스크 5: 토큰/비용 초과
원인: 복잡한 악성코드의 대량 디컴파일 + 소스 재구성
대응:
- max_budget_usd 설정
- 핵심 기능만 선택적 재구성 (C2 모듈 집중)
- Opus는 분석/재구성에만, 나머지는 Sonnet
리스크 6: 재빌드 무기의 기능 차이
원인: 컴파일러 차이, 최적화 차이로 원본과 행위 상이
대응:
- 샌드박스 행위 비교로 차이점 식별
- 핵심 기능(C2 통신, 안티디버깅)의 동작 검증 우선
- 비핵심 기능 차이는 설명서에 명시
12. 악성코드 분석 팀 / 레드팀과의 연동
악성코드 분석 팀과 공유
- ghidra-mcp 서버 완전 공유 (동일 인프라)
- Weapon Analyst와 악성코드 분석 팀의 Reverse Engineer는 유사 역할 → 프롬프트 에셋 공유 및 교차 개선 가능
- 악성코드 분석 팀의 분석 결과를 Weapon Builder의 입력으로 직접 활용 가능
레드팀과 연동
- Weapon Builder의 산출물(재빌드된 공격무기)을 레드팀에서 직접 사용
- 레드팀의 Exploit Operator가 재빌드된 무기를 배포/실행
- 워크플로우:
APT 샘플 확보 → Weapon Builder(분석+재빌드) → Red Team(배포+실행+보고) - 블루팀은 탐지 시그니처(YARA, 네트워크)를 기반으로 방어 훈련
3팀 통합 파이프라인 (향후)
APT 인텔리전스 → 샘플 확보
|
v
[악성코드 분석 팀] 심층 분석
|
v
[공격무기 빌더] C2 교체 + 재빌드
|
v
[레드팀] 위협 시뮬레이션 실행
|
v
[블루팀] 탐지/대응 훈련
부록: 핵심 코드 스켈레톤 (main.py)
# main.py - 공격무기 빌더 진입점
import asyncio
from claude_agent_sdk import ClaudeSDKClient, ClaudeAgentOptions, AgentDefinition
from mcp_servers.sample_mcp import create_sample_server
from mcp_servers.ghidra_mcp.server import create_ghidra_server
from mcp_servers.analysis_mcp import create_analysis_server
from mcp_servers.build_mcp.server import create_build_server
from mcp_servers.verification_mcp.server import create_verification_server
async def build_weapon(
sample_input: str, # 파일 경로 또는 SHA256 해시
user_c2_config: dict, # {"ip": "10.0.0.100", "domain": "test.local", "port": 443}
options_override: dict = None
):
# MCP 서버
sample_srv = create_sample_server()
ghidra_srv = create_ghidra_server()
analysis_srv = create_analysis_server()
build_srv = create_build_server()
verify_srv = create_verification_server()
# 에이전트 팀
options = ClaudeAgentOptions(
agents={
"commander": AgentDefinition(
description="공격무기 빌드 파이프라인 총괄",
prompt=load_prompt("prompts/commander.md"),
tools=["dispatch_task", "validate_output", "check_safety"],
model="opus",
),
"sample-acquirer": AgentDefinition(
description="악성코드 샘플 확보 및 분류",
prompt=load_prompt("prompts/sample_acquirer.md"),
tools=[sample_srv.tools],
model="sonnet",
),
"weapon-analyst": AgentDefinition(
description="악성코드 심층 분석 및 핵심 기능 추출",
prompt=load_prompt("prompts/weapon_analyst.md"),
tools=[ghidra_srv.tools, analysis_srv.tools],
model="opus",
),
"c2-replacer": AgentDefinition(
description="C2 통신 대상 교체 설계",
prompt=load_prompt("prompts/c2_replacer.md"),
tools=[analysis_srv.tools],
model="opus",
),
"code-reconstructor": AgentDefinition(
description="컴파일 가능 소스코드 재구성",
prompt=load_prompt("prompts/code_reconstructor.md"),
tools=[build_srv.tools],
model="opus",
),
"build-engineer": AgentDefinition(
description="빌드, 검증, 문서화",
prompt=load_prompt("prompts/build_engineer.md"),
tools=[build_srv.tools, verify_srv.tools],
model="sonnet",
),
},
max_budget_usd=15.0,
)
# 실행
async with ClaudeSDKClient(options=options) as client:
user_c2_json = json.dumps(user_c2_config, indent=2)
await client.query(
f"공격무기를 빌드해주세요.\n"
f"샘플: {sample_input}\n"
f"사용자 C2 인프라:\n{user_c2_json}\n"
)
result = []
async for msg in client.receive_response():
result.append(msg)
return result
if __name__ == "__main__":
import sys, json
sample = sys.argv[1]
c2_config = json.loads(sys.argv[2])
result = asyncio.run(build_weapon(sample, c2_config))
print(result)

댓글 남기기