content/writing/how-to-using-sysmon-for-Linux.md (18476B)
1 ---
2 title: "How to using sysmon for Linux"
3 titleKo: ""
4 date: 2025-12-07
5 deck: ""
6 type:
7 tags: []
8 draft:
9 ---
10
11 # Summary
12
13 Sysmon for Linux는 마이크로소프트 Sysinternals 도구 중 하나인 시스템 모니터(System monitor) 를 리눅스 환경으로 포팅한 강력한 보안 모니터링 도구이다.
14
15 윈도우 환경에서 침해 사고 분석과 위협 탐지의 표준처럼 쓰이던 Sysmon을 리눅스에서도 사용할 수 있다.
16
17 ## A. 핵심 원리: eBPF (Extended Berkeley Packet Filter)
18
19 Sysmon for Linux가 기존의 리눅스 감사 도구(auditd 등) 와 가장 차별화되는 점은 **eBPF**를 사용한다는 것이다.
20
21 - 동작 방식 : 커널 소스 코드를 수정하거나 모듈을 로드하지 않고도, 커널 내부의 특정 이벤트(시스템 호출, 네트워크 패킷 등) 를 안전하고 효율적으로 후킹(Hooking) 하여 모니터링한다.
22 - 장점 : 시스템 안정성을 해치지 않으면서 고성능으로 데이터를 수집할 수 있다. (과거 커널 모듈 방식의 시스템 충돌 위험을 최소화함)
23
24 ## B. 주요 기능 및 모니터링 항목
25
26 Sysmon은 윈도우 버전과 거의 동일한 이벤트 ID 체계를 사용하므로, 윈도우와 리눅스가 섞인 혼합 환경에서 통합 관제(SIEM) 를 구축하기 매우 유리하다.
27
28 주요 이벤트 ID는 다음과 같다.
29
30 - Event ID 1 (Process Creation) : 어떤 프로세스가 실행되었는지, 부모 프로세스는 무엇인지, 실행 시 명령어 인자(Command Line)는 무엇인지 기록한다. (가장 중요)
31 - Event ID 3 (Network Connection) : 프로세스가 외부와 통신할 때 IP, 포트, 프로토콜 정보를 기록한다.
32 - Event ID 5 (Process Terminate) : 프로세스가 언제 종료되었는지 기록한다.
33 - Event ID 9 (RawAccessRead) : 드라이브 섹터에 대한 직접 읽기를 탐지한다.
34 - Event ID 11 (FileCreate) : 파일이 생성되거나 덮어써질 때를 기록한다. (랜섬웨어 탐지 등에 유용)
35
36 ## C. 로그 저장 위치
37
38 윈도우에서는 '이벤트 뷰어'에 저장되지만, 리눅스에서는 표준 로깅 시스템을 따른다.
39
40 - Syslog : /var/log/syslog (또는 /var/log/messages)
41 - Journald : journalctl 명령어로 조회 가능
42 - 로그 포맷은 XML 형태를 텍스트로 변환하여 저장하므로, Splunk나 ELK 같은 SIEM 도구로 전송하여 파싱하기좋다.
43
44 ## D. 기존 리눅스 도구(Auditd)와의 비교
45
46 | 특성 | Sysmon for Linux | Auditd (Linux Audit Framework) |
47 | --- | --- | --- |
48 | 기반 기술 | eBPF (최신, 고성능) | Kernel Audit Subsystem (전통적) |
49 | 로그 가독성 | 높음 (구조화된 데이터, 관계 파악 용이) | 낮음 (해석이 어렵고 파싱이 까다로움) |
50 | 필터링 | 강력함 (XML 기반의 상세 조건 설정) | 가능하지만 규칙 작성이 복잡함 |
51 | 플랫폼 통합 | Windows/Linux 로그 포맷 통일 가능 | 리눅스 전용 |
52 | 상태 | 실행 프로세스 트리 추적 용이 | 단일 이벤트 위주 |
53
54 ## E. 설치
55
56 ### E.1. 마이크로소프트 저장소 키 및 패키지 등록
57
58 ```bash
59 # 1. 설치 파일 다운로드
60 $ wget -q https://packages.microsoft.com/config/ubuntu/$(lsb_release -rs)/packages-microsoft-prod.deb -O packages-microsoft-prod.deb
61
62 # 2. 다운로드한 패키지 설치 (저장소 등록)
63 $ sudo dpkg -i packages-microsoft-prod.deb
64 ```
65
66 ### E.2. Sysmon 설치
67
68 ```bash
69 # 1. 패키지 목록 업데이트
70 $ sudo apt-get update
71
72 # 2. Sysmon for Linux 설치
73 $ sudo apt-get install sysmonforlinux
74 ```
75
76 ## F. 설정 파일 생성
77
78 설정파일(XML) 을 지정하고 서비스를 시작해야 Sysmon 이 동작 한다.
79
80 #### sysmon-config.xml
81
82 ```xml
83 <Sysmon schemaversion="4.81">
84 <HashAlgorithms>sha256</HashAlgorithms>
85
86 <EventFiltering>
87
88 <RuleGroup name="Terminate_Silence" groupRelation="or">
89 <ProcessTerminate onmatch="include">
90 <Image condition="is">THIS_PROCESS_WILL_NEVER_EXIST_12345</Image>
91 </ProcessTerminate>
92 </RuleGroup>
93
94 <RuleGroup name="ProcessCreate_Security" groupRelation="or">
95
96 <ProcessCreate onmatch="exclude">
97 <Image condition="end with">gnome-shell</Image> <Image condition="end with">tracker-miner-fs-3</Image> <Image condition="end with">vmtoolsd</Image> <Image condition="is"><unknown process></Image> <CommandLine condition="contains">tmux-continuum</CommandLine> <CommandLine condition="contains">continuum_save.sh</CommandLine> <CommandLine condition="contains">check_tmux_version.sh</CommandLine> <CommandLine condition="contains">cpuUsage.sh</CommandLine> <CommandLine condition="contains">extensionHost</CommandLine> <CommandLine condition="contains">which ps</CommandLine> <CommandLine condition="contains">/usr/bin/ps</CommandLine> </ProcessCreate>
98
99 <ProcessCreate onmatch="include">
100 <Image condition="end with">bash</Image>
101 <Image condition="end with">sh</Image>
102 <Image condition="end with">dash</Image>
103 <Image condition="end with">zsh</Image>
104
105 <Image condition="end with">sudo</Image>
106 <Image condition="end with">su</Image>
107
108 <Image condition="end with">python3</Image>
109 <Image condition="end with">perl</Image>
110 <Image condition="end with">gcc</Image>
111 <Image condition="end with">g++</Image>
112
113 <Image condition="end with">curl</Image>
114 <Image condition="end with">wget</Image>
115 <Image condition="end with">nc</Image> <Image condition="end with">ncat</Image>
116 <Image condition="end with">ssh</Image> <Image condition="end with">scp</Image> <Image condition="end with">ftp</Image>
117 <Image condition="end with">socat</Image>
118 </ProcessCreate>
119 </RuleGroup>
120
121 <RuleGroup name="Network_Security" groupRelation="or">
122 <NetworkConnect onmatch="include">
123 <Image condition="end with">curl</Image>
124 <Image condition="end with">wget</Image>
125 <Image condition="end with">nc</Image>
126
127 <Image condition="end with">bash</Image>
128 <Image condition="end with">sh</Image>
129
130 <Image condition="end with">python3</Image>
131
132 <Image condition="end with">ssh</Image>
133 </NetworkConnect>
134 </RuleGroup>
135
136 </EventFiltering>
137 </Sysmon>
138 ```
139
140 ## G. 설정 적용
141
142 ### G.1 만든 파일을 로드하여 Sysmon을 시작 or 재시작
143
144 ```bash
145 $ sudo sysmon -i sysmon-config.xml
146 ```
147
148 ### G.2 이미 실행 중이라면 설정을 업데이트(-c)
149
150 ```bash
151 $ sudo sysmon -c sysmon-config.xml
152 ```
153
154 ## H. 로그 확인하기
155
156 ```bash
157 # Ubuntu의 기본 시스템 로그 파일 모니터링
158 $ sudo tail -f /var/log/syslog | grep "Linux-Sysmon"
159 ```
160
161 ### H.1 가독성이 떨어지는 로그
162
163 ```bash
164 2025-12-10T22:27:58.152234+09:00 x sysmon: <Event><System><Provider Name="Linux-Sysmon" Guid="{ff032593-a8d3-4f13-b0d6-01fc615a0f97}"/><EventID>1</EventID><Version>5</Version><Level>4</Level><Task>1</Task><Opcode>0</Opcode><Keywords>0x8000000000000000</Keywords><TimeCreated SystemTime="2025-12-10T13:27:58.151790000Z"/><EventRecordID>16525</EventRecordID><Correlation/><Execution ProcessID="1296720" ThreadID="1296720"/><Channel>Linux-Sysmon/Operational</Channel><Computer>x</Computer><Security UserId="0"/></System><EventData><Data Name="RuleName">ProcessCreate_Security</Data><Data Name="UtcTime">2025-12-02 06:14:11.408</Data><Data Name="ProcessGuid">{3e748dcd-83b3-692e-d10b-c636f7560000}</Data><Data Name="ProcessId">1979575</Data><Data Name="Image">/usr/bin/sudo</Data><Data Name="FileVersion">-</Data><Data Name="Description">-</Data><Data Name="Product">-</Data><Data Name="Company">-</Data><Data Name="OriginalFileName">-</Data><Data Name="CommandLine">sudo tail -f /var/log/syslog</Data><Data Name="CurrentDirectory">/home/devastator/.config</Data><Data Name="User">devastator</Data><Data Name="LogonGuid">{3e748dcd-65f1-6934-e803-000002000000}</Data><Data Name="LogonId">1000</Data><Data Name="TerminalSessionId">3</Data><Data Name="IntegrityLevel">no level</Data><Data Name="Hashes">SHA256=654d953098b5dd26fcc3af44d4cf6e986f61f84ad9198d57722702c6034bd686</Data><Data Name="ParentProcessGuid">{3e748dcd-7503-692e-9553-b55339630000}</Data><Data Name="ParentProcessId">1907076</Data><Data Name="ParentImage">/usr/bin/zsh</Data><Data Name="ParentCommandLine">zsh</Data><Data Name="ParentUser">devastator</Data></EventData></Event>
165 2025-12-10T22:28:07.111277+09:00 x sysmon: <Event><System><Provider Name="Linux-Sysmon" Guid="{ff032593-a8d3-4f13-b0d6-01fc615a0f97}"/><EventID>1</EventID><Version>5</Version><Level>4</Level><Task>1</Task><Opcode>0</Opcode><Keywords>0x8000000000000000</Keywords><TimeCreated SystemTime="2025-12-10T13:28:07.110532000Z"/><EventRecordID>16526</EventRecordID><Correlation/><Execution ProcessID="1296720" ThreadID="1296720"/><Channel>Linux-Sysmon/Operational</Channel><Computer>x</Computer><Security UserId="0"/></System><EventData><Data Name="RuleName">ProcessCreate_Security</Data><Data Name="UtcTime">2025-12-02 06:14:20.366</Data><Data Name="ProcessGuid">{3e748dcd-83bc-692e-d15b-68e08b590000}</Data><Data Name="ProcessId">1979719</Data><Data Name="Image">/usr/bin/sudo</Data><Data Name="FileVersion">-</Data><Data Name="Description">-</Data><Data Name="Product">-</Data><Data Name="Company">-</Data><Data Name="OriginalFileName">-</Data><Data Name="CommandLine">sudo</Data><Data Name="CurrentDirectory">/home/devastator/.config</Data><Data Name="User">devastator</Data><Data Name="LogonGuid">{3e748dcd-62c8-6934-e803-000001000000}</Data><Data Name="LogonId">1000</Data><Data Name="TerminalSessionId">3</Data><Data Name="IntegrityLevel">no level</Data><Data Name="Hashes">SHA256=654d953098b5dd26fcc3af44d4cf6e986f61f84ad9198d57722702c6034bd686</Data><Data Name="ParentProcessGuid">{00000000-0000-0000-0000-000000000000}</Data><Data Name="ParentProcessId">1237687</Data><Data Name="ParentImage">-</Data><Data Name="ParentCommandLine">-</Data><Data Name="ParentUser">-</Data></EventData></Event>
166 ```
167
168 하지만 XML 형식의 로그가 쏟아져 나와 가독성이 매우 떨어지므로 무분별한 로그를 정제하기 위해 Python 뷰어 스크립트가 필요하다
169
170 ## I. 뷰어 스크립트 생성
171
172 ### sysmon_view.py
173
174 ```python
175 import sys
176 import xml.etree.ElementTree as ET
177
178 # ==============================================================================
179 # [스크립트 설명]
180 # Sysmon for Linux가 생성하는 XML 형식의 로그를 실시간으로 파싱
181 # 'tail -f /var/log/syslog' 명령어와 파이프(|)로 연결되어 실행
182 #
183 # [주요 기능]
184 # 1. 복잡한 XML 태그 제거 및 데이터 추출
185 # 2. 불필요한 노이즈(Event ID 5 등) 필터링
186 # 3. 중요 이벤트(프로세스 생성, 네트워크 연결) 컬러 강조
187 # 4. 파일 해시(SHA256) 값 출력 지원
188 # ==============================================================================
189
190 def get_tag_name(elem):
191 """
192 XML 태그에서 네임스페이스(Namespace) URL을 제거하고, 순수 태그 이름만 추출하는 함수
193
194 [예시]
195 입력: {http://schemas.microsoft.com/schemas/eventlog/main}EventID
196 출력: EventID
197
198 이유: Sysmon 로그는 표준 포맷을 따르기 때문에 태그 앞에 긴 URL이 붙어있어,
199 이를 제거해야 데이터 처리가 쉬움
200 """
201 if '}' in elem.tag:
202 # '}' 문자를 기준으로 쪼개서 뒷부분(진짜 이름)만 가져옴
203 return elem.tag.split('}', 1)[1]
204 return elem.tag
205
206 def parse_and_print():
207 """
208 표준 입력(stdin)으로 들어오는 로그를 한 줄씩 읽어서 분석하고 출력하는 메인 함수
209 """
210
211 # 1. 시작 배너 출력 (스크립트가 실행되었음을 알림)
212 print("\n" + "="*70)
213 print(" 🛡️ Sysmon Log Viewer (Detailed Comment Version)")
214 print(" waiting for security events... (Noise filtered)")
215 print("="*70 + "\n")
216
217 # 2. 실시간 로그 읽기 루프 (파이프로 연결된 데이터가 들어올 때마다 반복)
218 for line in sys.stdin:
219 try:
220 # Sysmon 로그인지 확인 (로그 라인에 <Event> 태그가 있는지 검색)
221 start_idx = line.find('<Event>')
222
223 # <Event> 태그가 없으면 Sysmon 로그가 아니거나 빈 줄이므로 건너뜀
224 if start_idx == -1:
225 continue
226
227 # XML 데이터 부분만 잘라냄
228 xml_data = line[start_idx:]
229
230 # 3. XML 파싱 (문자열을 구조화된 데이터로 변환)
231 try:
232 root = ET.fromstring(xml_data)
233 except ET.ParseError:
234 # XML 형식이 깨져있으면 무시하고 다음 줄로 넘어감
235 continue
236
237 # 데이터를 저장할 변수 초기화
238 event_id = "Unknown"
239 data_map = {} # <Data Name="Key">Value</Data> 형태를 저장할 딕셔너리
240
241 # 4. XML 내부 순회 및 데이터 추출
242 for elem in root.iter():
243 tag = get_tag_name(elem) # 태그 이름 정제
244
245 # 이벤트 ID 추출 (<EventID>1</EventID>)
246 if tag == 'EventID':
247 event_id = elem.text
248
249 # 상세 데이터 추출 (<Data Name="Image">/usr/bin/sudo</Data>)
250 elif tag == 'Data':
251 name_attr = elem.attrib.get('Name') # Name 속성 값 가져오기 (예: Image, User)
252 if name_attr:
253 # 텍스트가 있으면 가져오고, 없으면 빈 문자열 저장
254 data_map[name_attr] = elem.text if elem.text else ""
255
256 # 5. 필터링
257 # Event ID 5 (Process Terminate)는 노이즈가 되므로 출력하지 않음
258 if event_id == "5":
259 continue
260
261 # 6. 출력에 사용할 공통 필드 가져오기 (없으면 기본값 사용)
262 time = data_map.get('UtcTime', 'Unknown Time') # 발생 시간
263 image = data_map.get('Image', 'Unknown Process') # 실행된 프로세스 경로
264 user = data_map.get('User', '-') # 실행한 사용자
265
266 # 7. ANSI 색상 코드 정의 (터미널에서 색을 입히기 위함)
267 RESET = "\033[0m" # 색상 초기화
268 GREEN = "\033[92m" # 초록색 (프로세스 생성)
269 RED = "\033[91m" # 빨간색 (네트워크 연결 - 위험)
270 BLUE = "\033[94m" # 파란색 (파일 생성)
271 GRAY = "\033[90m" # 회색 (부가 정보/해시)
272 BOLD = "\033[1m" # 굵게 강조
273
274 # 8. 이벤트 ID별 출력 포맷 설정
275
276 # [CASE 1] Event ID 1: 프로세스 생성
277 if event_id == "1":
278 cmd = data_map.get('CommandLine', '') # 실행된 명령어 전체
279 hashes = data_map.get('Hashes', '') # SHA256 등 해시값
280
281 # 메인 정보 출력
282 print(f"{GREEN}[CREATE]{RESET} {time} | {BOLD}{image}{RESET} | User: {user} | {cmd}")
283
284 # 해시값이 존재하면, 바로 아랫줄에 회색으로 들여쓰기하여 출력
285 if hashes:
286 print(f" └─ {GRAY}Hash: {hashes}{RESET}")
287
288 # [CASE 2] Event ID 3: 네트워크 연결 (외부 통신)
289 elif event_id == "3":
290 dest_ip = data_map.get('DestinationIp', '-') # 목적지 IP
291 dest_port = data_map.get('DestinationPort', '-') # 목적지 포트
292 protocol = data_map.get('Protocol', 'tcp') # 프로토콜 (tcp/udp)
293
294 print(f"{RED}[NET]{RESET} {time} | {image} -> {dest_ip}:{dest_port} ({protocol})")
295
296 # [CASE 3] Event ID 11: 파일 생성 (악성코드 드롭 등)
297 elif event_id == "11":
298 target = data_map.get('TargetFilename', '-') # 생성된 파일 경로
299
300 print(f"{BLUE}[FILE]{RESET} {time} | {image} created -> {target}")
301
302 # [CASE 4] 그 외 이벤트 (설정 변경 등)
303 else:
304 print(f"[ID {event_id}] {time} | {image}")
305
306 except Exception as e:
307 # 실행 중 예상치 못한 에러가 발생해도 스크립트가 꺼지지 않게 처리
308 # (디버깅이 필요할 땐 아래 pass를 print(e)로 바꾸면 됨)
309 pass
310
311 # 스크립트가 직접 실행될 때만 parse_and_print() 함수 실행
312 if __name__ == "__main__":
313 parse_and_print()
314 ```
315
316 ## J. 뷰어 스크립트 실행
317
318 ```bash
319 $ sudo tail -f /var/log/syslog | python3 -u sysmon_view.py
320 ```
321
322 #### 결과값 예시
323
324 ```bash
325 ======================================================================
326 🛡️ Sysmon Log Viewer (Detailed Comment Version)
327 waiting for security events... (Noise filtered)
328 ======================================================================
329
330 [CREATE] 2025-12-02 05:03:30.832 | /usr/bin/sudo | User: devastator | sudo tail -f /var/log/syslog
331 └─ Hash: SHA256=654d953098b5dd26fcc3af44d4cf6e986f61f84ad9198d57722702c6034bd686
332 [CREATE] 2025-12-02 05:03:39.391 | /usr/bin/ssh | User: devastator | ssh
333 └─ Hash: SHA256=ffc312252dd2756e3346f1fd5a680486a4073abef452d44939351742d9b4bba0
334 [CREATE] 2025-12-02 05:03:42.230 | /usr/bin/curl | User: devastator | curl google.com
335 └─ Hash: SHA256=aca992dba6da014cd5baaa739624e68362c8930337f3a547114afdbd708d06a4
336 [NET] 2025-12-02 05:03:42.271 | /usr/bin/curl -> 127.0.0.1:36697 (udp)
337 [NET] 2025-12-02 05:03:42.306 | /usr/bin/curl -> 142.250.206.206:80 (tcp)
338 ```
339
340 
341
342 Python 뷰어 스크립트를 통해 출력된 결과값은 필요한 정보만 확인할 수 있어 매우 가독성을 높혀준다.
343
344 Ubuntu 24.04 에서 각각의 명령어의 Hash(SHA256) 값을 확인 할 수 있다.
345
346 #### ssh
347
348 - SHA256=ffc312252dd2756e3346f1fd5a680486a4073abef452d44939351742d9b4bba0
349
350 #### curl
351
352 - SHA256=aca992dba6da014cd5baaa739624e68362c8930337f3a547114afdbd708d06a4
353
354 #### wget
355
356 - SHA256=b8f8a975cf3e7908e076de79814aa448c6086aacfc08165be04ce65665e08e39
357
358 ### References
359
360 [1] [https://github.com/microsoft/SysmonForLinux.git](https://github.com/microsoft/SysmonForLinux.git?ref=openpesto.com)