Zeek files.log와 pe.log¶
한 줄 요약
Zeek이 이해하는 모든 프로토콜(HTTP, SMTP, FTP, SMB, IRC, TLS 인증서…)로 오가는 파일마다 추정 타입, 크기, 해시, 실어 나른 연결이 이곳에 한 줄씩 기록됩니다. pe.log는 Windows 실행 파일의 헤더 정보를 더합니다 — 그래서 "네트워크로 무엇이 다운로드/업로드/복사됐고, 그게 악성인가"를 pcap을 열지 않고 답하는 곳입니다.
files.log 필드¶
| 필드 | 의미 | 분석 메모 |
|---|---|---|
ts |
파일을 처음 본 시각 | |
fuid |
파일 고유 ID | 결합 키: http.log resp_fuids/orig_fuids, smtp.log fuids, ssl.log cert_chain_fuids, smb_files.log fuid, pe.log id |
uid (Zeek 6+) / conn_uids (구버전) |
실어 나른 연결 | → conn.log |
id.orig_h, id.resp_h (6+) / tx_hosts, rx_hosts (구버전) |
보낸 쪽 / 받은 쪽 | HTTP 다운로드라면: tx = 서버, rx = 클라이언트 |
source |
프로토콜: HTTP, SMTP, FTP_DATA, SMB, SSL (인증서), IRC_DATA, KRB |
|
depth |
중첩 깊이 (예: MIME 안) | |
analyzers |
붙은 분석기: MD5, SHA1, SHA256, PE, EXTRACT, X509 |
해시가 비어 있으면 분석기가 로드되지 않은 것 |
mime_type |
매직 바이트로 추정한 타입 | HTTP 헤더 / 파일명보다 이걸 믿을 것 |
filename |
Content-Disposition, URI, SMB 경로, MIME에서 |
HTTP에서는 비어 있는 경우가 많음 |
duration |
전송 시간 | |
local_orig |
보낸 쪽이 내부인지 | |
is_orig |
연결 시작 측이 보낸 파일인가? | T = 클라이언트의 업로드, F = 다운로드 |
seen_bytes / total_bytes |
Zeek이 본 바이트 / 선언된 크기 | 다르면 → 잘림 (missing_bytes, overflow_bytes) |
missing_bytes, overflow_bytes, timedout |
공백 / 크기 초과 / 시간 초과 | 하나라도 0이 아니면 해시를 믿기 어려움 |
parent_fuid |
컨테이너 파일 | 예: 이메일 안의 첨부 파일 |
md5, sha1, sha256 |
해시 (분석기가 켜져 있다면) | 이것으로 위협 인텔리전스를 검색 |
extracted |
추출된 사본 경로 (EXTRACT가 켜져 있다면) |
extract_files/HTTP-FdvK1A3z4tPEujBU9c.exe |
extracted_cutoff, extracted_size |
추출 잘림 정보 |
pe.log 필드 (Windows PE 파일만)¶
| 필드 | 의미 | 분석 메모 |
|---|---|---|
id |
= fuid |
|
machine |
I386, AMD64, ARM64 |
|
compile_ts |
PE 헤더 타임스탬프 | 미래 / 아주 오래됨 / 다른 샘플과 일치 → 위조 또는 패밀리 표식 |
os, subsystem |
Windows XP+, WINDOWS_GUI / WINDOWS_CUI (콘솔) |
실제로는 콘솔 로더인 "GUI" 앱; NATIVE = 드라이버 |
is_exe, is_64bit |
is_exe=F = DLL/드라이버 |
|
uses_aslr, uses_dep, uses_code_integrity, uses_seh |
보안 완화 기능 | 악성코드와 오래된 도구는 ASLR/DEP가 없는 경우가 많음 |
has_import_table, has_export_table, has_cert_table, has_debug_data |
테이블 존재 여부 | 임포트 테이블 없음 → 패킹; has_cert_table=T → 서명됨 (서명은 호스트에서 확인) |
section_names |
섹션 이름 | .text .rdata .data .rsrc .reloc가 정상; UPX0, .vmp0, .themida, 무작위 이름 → 패킹 |
해시와 추출 켜기¶
기본으로는 MD5만 돕니다(배포판에 따라 아무것도 안 돌기도 함). local.zeek이나 명령줄에서:
@load policy/frameworks/files/hash-all-files # md5 + sha1 + sha256 for every file
@load policy/frameworks/files/extract-all-files # write every file to extract_files/ (disk!)
# Or extract only executables:
event file_sniff(f: fa_file, meta: fa_metadata) {
if ( meta?$mime_type && meta$mime_type == "application/x-dosexec" )
Files::add_analyzer(f, Files::ANALYZER_EXTRACT);
}
redef FileExtract::prefix = "/data/zeek/extract/";
redef FileExtract::default_limit = 50000000; # 50 MB cap per file
zeek -C -r capture.pcap local policy/frameworks/files/hash-all-files policy/frameworks/files/extract-all-files
ls extract_files/ # HTTP-F..., SMTP-F..., SMB-F... (named by source + fuid)
빠른 쿼리¶
# All executables, scripts, archives and Office docs that crossed the wire
zeek-cut -d ts fuid source id.orig_h id.resp_h mime_type filename total_bytes sha256 < files.log \
| grep -E 'x-dosexec|x-msdownload|x-executable|zip|x-rar|x-7z|msword|officedocument|vnd.ms-|x-shellscript|hta|javascript|x-powershell'
# Uploads (is_orig = T) leaving the network — exfil / web-shell uploads
zeek-cut -d ts source id.orig_h id.resp_h mime_type total_bytes filename < files.log | awk -F'\t' '$0 ~ /\tT\t/' # (add is_orig to the cut)
# SMB file copies between internal hosts (lateral movement, staging)
zeek-cut -d ts id.orig_h id.resp_h filename mime_type total_bytes < files.log | awk -F'\t' '$1 ~ /SMB/ || 1' | grep -F 'SMB'
# better: smb_files.log
zeek-cut -d ts id.orig_h id.resp_h action path name size < smb_files.log | grep -E 'WRITE|OPEN' | grep -iE '\.(exe|dll|ps1|bat|vbs|sys)\b'
# Hash list for VT / intel lookup
zeek-cut sha256 mime_type < files.log | awk '$2 ~ /dosexec|zip|msword|officedocument/ && $1!="-" {print $1}' | sort -u > hashes.txt
# PE: unusual sections / no ASLR / console apps downloaded via HTTP
zeek-cut id machine compile_ts subsystem uses_aslr has_import_table section_names < pe.log \
| awk -F'\t' '$5=="F" || $6=="F" || $7 !~ /\.text/'
# From a file back to the URL that served it
grep -F 'FdvK1A3z4tPEujBU9c' http.log | zeek-cut -d ts id.orig_h host uri user_agent
index=zeek sourcetype=zeek:files mime_type IN ("application/x-dosexec","application/x-msdownload","application/zip","application/x-rar","application/msword","application/vnd.openxmlformats-officedocument.wordprocessingml.document")
| stats values(filename) as names values(source) as proto dc(id.resp_h) as receivers count by sha256, mime_type, total_bytes
| sort - count
위험한 파일 타입을 모두 해시별로 묶고, 어떤 파일명으로 이동했는지(values(filename))와 몇 대가 받았는지(dc(id.resp_h))를 나열합니다. 해시 하나가 여러 호스트에 다른 이름으로 도착한다면 웜이거나 횡적 이동 중에 뿌려지는 도구입니다.
index=zeek sourcetype=zeek:files is_orig=true local_orig=true
| eval MB=round(total_bytes/1024/1024,2)
| stats sum(MB) as total_MB count by id.orig_h, id.resp_h, source
| where total_MB > 50
is_orig=true는 클라이언트가 파일을 보냈다(업로드)는 뜻이고, local_orig=true는 그 클라이언트가 내부에 있다는 뜻입니다. 내부→외부 쌍마다 업로드한 메가바이트를 더하고 50 MB를 넘는 것만 남기면 간단한 유출 헌팅이 됩니다.
분석 팁¶
해시 → 인텔리전스 → 호스트, 이 순서로
해당 시간대의 모든 실행 파일/압축 파일/Office 파일의 sha256을 뽑아 VirusTotal/MISP/EDR과 대조하고, 나쁜 해시마다 받은 호스트의 Amcache(같은 SHA-1 — files.log의 sha1 사용)와 Prefetch로 가서 도착하고 실행됐음을 증명하세요. pcap을 열지 않고 다운로드→실행 체인이 완성됩니다.
- 추정 MIME이 진실입니다.
filename과 HTTPContent-Type은 공격자가 정합니다.filename=invoice.pdf인데mime_type=application/x-dosexec라면 그게 발견입니다. - 일부만 받은 파일:
missing_bytes > 0이거나timedout = T라면 해시가 VT와 맞지 않습니다 — 센서가 패킷을 놓친 것입니다. "알 수 없는 파일"이라고 하지 말고 그렇게 적으세요. - SMB 복사는 두 번 나타납니다:
files.log(source=SMB, 파일 분석기가 동작했다면)와smb_files.log(action=SMB::FILE_WRITE/OPEN/CLOSE,path=\\host\C$,name).ADMIN$에*.exe를WRITE한 뒤dce_rpc.log에CreateServiceW/StartServiceW= PsExec 방식 횡적 이동 (공격 기법 섹션 참고). - 이메일 첨부 파일:
source=SMTP,parent_fuid있음,filename은 MIME에서;smtp.log(mailfrom,rcptto,subject,fuids)와 결합하면 보낸 사람 → 받는 사람 → 첨부 → 해시가 한 줄에 나옵니다. - 인증서도 파일입니다 (
source=SSL,mime_type=application/x-x509-user-cert) — 그래서x509.log가fuid로 결합됩니다. "진짜" 파일을 셀 때는 걸러 내세요. pe.log빠른 위험 신호:compile_ts가ts와 몇 시간 차이 (막 빌드됨), 표준이 아닌 섹션 이름,has_import_table=F, 64비트 바이너리인데uses_aslr=F, 설치 프로그램이라고 주장하는데subsystem=WINDOWS_CUI.- 추출 위생: 추출한 악성코드는 살아 있는 악성코드입니다 — 격리된 분석 장비로 추출하고, 바쁜 센서에서는
extract_files/가 디스크를 금방 채울 수 있다는 점을 기억하세요. 운영 환경에서는 위의 MIME 필터 추출 스크립트를 쓰세요. - 다 비어 있나요?
analyzers를 확인하세요 —X509만 있거나 비어 있다면 로그를 만들 때 해시 정책이 로드되지 않은 것입니다. pcap에 정책을 넣어 Zeek을 다시 돌리세요.
상관분석¶
| 질문 | 다음에 볼 곳 |
|---|---|
| 어디서 와서 어디로 갔나? | uid → conn.log; fuid → http.log (host, uri), smtp.log, smb_files.log, ftp.log |
| 받은 호스트에서 실행됐나? | Prefetch, Amcache (SHA-1), 4688/Sysmon 1; $MFT의 Zone.Identifier에 다운로드 URL이 있음 |
| 알려진 악성인가? | VirusTotal, MalwareBazaar, MISP; Suricata 파일 규칙 (eve.json의 fileinfo 이벤트가 md5/sha256을 공유) |
| 퍼졌나? | id.resp_h 전반에 stats … by sha256; smb_files.log에서 ADMIN$/C$로의 SMB 쓰기 |
| 무엇을 하나? | extract_files/<fuid>의 정적/동적 분석; 첫 확인은 pe.log |