서문
ICEDID는 IBM X-force 연구원이 2017 에서 발견한멀웨어군으로 로그인 자격 증명, 은행 정보 및 기타 개인 정보 도용과 관련이 있습니다. ICEDID는 항상 널리 알려진 제품군이었지만 2021년 초에 EMOTET이 일시적으로 중단된 이후 더 큰 성장을 이루었습니다. ICEDID는 DarkVNC 및 COBALT STRIKE를 비롯한 여러 멀웨어 제품군의 유포와 관련이 있습니다. 이와 같은 연구 간행물을 포함한 정기적인 업계 보고는 이러한 위협을 완화하는 데 도움이 됩니다.
ICEDID는 사용자 지정 파일 형식과 사용자 지정 암호화 체계를 사용하여 페이로드를 패킹하는 것으로 알려져 있습니다. GZip 변종 실행 체인을 다루는 최신 ICEDID 연구를 따르세요.
이 튜토리얼에서는 가짜 GZip 바이너리 사본을 다운로드하는 것부터 시작하여 최신 ICEDID 샘플의 포장을 풀면서 이러한 도구를 소개합니다:
멀웨어 분석은 시스템에 위험할 수 있으므로 격리된 가상 머신이나 분석 샌드박스와 같이 통제된 환경에서 숙련된 전문가만 시도해야 합니다. 멀웨어는 탐지를 회피하고 다른 시스템을 감염시키도록 설계될 수 있으므로 필요한 모든 예방 조치를 취하고 특수 도구를 사용하여 자신과 시스템을 보호하는 것이 중요합니다.
54d064799115f302a66220b3d0920c1158608a5ba76277666c4ac532b53e855f
환경 설정
이 튜토리얼에서는 Windows 10 및 Python 3.10을 사용합니다.
Elastic Security Labs는 언패킹 프로세스를 자동화하고 분석가와 커뮤니티가 ICEDID에 대응할 수 있도록 지원하는 도구 세트를 출시합니다.
스크립트 | 설명 | 호환성 |
---|---|---|
decrypt_file.py | ICEDID 암호화된 파일 해독 | Windows 및 기타(테스트되지 않음) |
gzip_variant/extract_gzip.py | ICEDID 가짜 GZip 파일에서 페이로드 추출하기 | Windows 및 기타(테스트되지 않음) |
gzip_variant/extract_payload_from_core.py | 재구축된 ICEDID 코어 바이너리에서 페이로드 추출 및 복호화 | Windows 및 기타(테스트되지 않음) |
gzip_variant/load_core.py | 핵심 커스텀 PE 바이너리 로드 및 실행 | Windows 전용 |
gzip_variant/read_configuration.py | 가짜 GZip에 포함된 ICEDID 구성 파일 읽기 | Windows 및 기타(테스트되지 않음) |
rebuild_pe.py | ICEDID 사용자 지정 PE 파일에서 PE 다시 빌드하기 | Windows 및 기타(테스트되지 않음) |
도구를 사용하려면 Elastic Security Lab 릴리즈 리포지토리를 복제하고 nightMARE 모듈을 설치하세요.
git clone https://github.com/elastic/labs-releases
cd labs-release
pip install .\nightMARE\
이 튜토리얼의 모든 도구는 nightMARE 모듈을 사용하며, 이 라이브러리는 ICEDID에 포함된 다양한 페이로드를 언패킹하는 데 필요한 다양한 알고리즘을 구현합니다. 이번 ICEDID 분석에 필요한 기능이기 때문에 밤마법을 공개하지만, 이 프레임워크를 계속 개발하고 발전시켜 나가면서 더 많은 기능이 추가될 예정이니 계속 지켜봐 주시기 바랍니다.
가짜 GZip 압축 풀기
ICEDID 가짜 GZip은 실제 데이터를 GZip 헤더와 바닥글로 캡슐화하여 형식이 유효한 GZip 파일인 것처럼 가장한 파일입니다.
GZip 매직 바이트는 빨간색으로 표시됩니다.
GZip 헤더는 녹색으로 렌더링됩니다.
더미 파일 이름 값은 파란색입니다.
GZip 헤더 뒤에는 아래에서 설명하는 실제 데이터 구조가 있습니다.
이 사기성 GZip의 압축을 풀기 위해 labs-releases\tools\icedid\gzip-variant\extract_gzip.py 스크립트를 사용하겠습니다.
usage: extract_gzip.py [--help] input output
positional arguments:
input Input file
output Output directory
options:
-h, --help show this help message and exit
위에 링크된 ICEDID 샘플의 extract_gzip.py를 사용하여 " extract "라는 이름의 폴더에 내용을 저장합니다(기존 출력 폴더를 사용할 수 있습니다).
python extract_gzip.py 54d064799115f302a66220b3d0920c1158608a5ba76277666c4ac532b53e855f extract
============================================================
Fake Gzip
============================================================
is_dll: True
core: UponBetter/license.dat (354282 bytes)
stage_2: lake_x32.tmp (292352 bytes)
extract\configuration.bin
extract\license.dat
extract\lake_x32.tmp
이 스크립트는 다음으로 구성된 세 개의 개별 파일을 반환합니다:
- 암호화된 구성 파일: configuration.bin
- 암호화된 핵심 바이너리: license.dat
- 지속성 로더: lake_x32.tmp
핵심 바이너리 및 구성 파일 해독하기
저희가 추출한 구성과 핵심 바이너리는 ICEDID의 사용자 지정 암호화 체계를 사용하여 암호화됩니다. 랩-리리즈\도구\아이디\decrypt_file.py 스크립트를 사용하여 암호를 해독할 수 있습니다.
usage: decompress_file.py [--help] input output
positional arguments:
input Input file
output Output file
options:
-h, --help show this help message and exit
여기에 설명된 대로(복호화된 파일은 모든 유효한 대상에 쓸 수 있습니다):
python .\decrypt_file.py .\extract\license.dat .\extract\license.dat.decrypted
python .\decrypt_file.py .\extract\configuration.bin .\extract\configuration.bin.decrypted
이제 코어 바이너리와 구성은 추가 도구로 처리할 준비가 되었습니다. 다음 스크린샷에 제시된 해독된 구성의 데이터를 참조하세요:
구성 읽기
구성 파일 형식은 다음과 같습니다.
이 구성은 labs-releases\tools\icedid\gzip-variant\read_configuration.py 스크립트를 사용하여 읽을 수 있습니다.
usage: read_configuration.py [--help] input
positional arguments:
input Input file
options:
-h, --help show this help message and exit
read_configuration.py 스크립트를 사용하여 이전 단계에서 수집한 configuration.bin.decrypted 파일을 읽겠습니다.
python .\gzip-variant\read_configuration.py .\extract\configuration.bin.decrypted
============================================================
Configuration
============================================================
botnet_id: 0x3B7D6BA4
auth_var: 0x00000038
uri: /news/
domains:
alishaskainz.com
villageskaier.com
이 구성에는 두 개의 C2 도메인이 포함되어 있습니다:
- alishaskainz[.]com
- villageskaier[.]com
이 샘플에서 ICEDID가 사용하는 비콘 URI는 " /뉴스/ " 입니다.
정적 분석을 위한 코어 바이너리 다시 빌드하기
ICEDID는 사용자 지정 PE 형식을 사용하여 페이로드를 난독화하므로 정상적인 Windows 실행 파일을 처리할 것으로 예상되는 정적 또는 동적 분석 도구를 무력화할 수 있습니다. 사용자 지정 PE 파일 형식은 아래에 설명되어 있습니다.
예를 들어 IDA Pro로 코어 바이너리를 분석하려면 유효한 PE로 다시 빌드해야 합니다. 랩-리리즈\도구\아이디\재빌드_pe.py 스크립트를 사용합니다.
usage: rebuild_pe.py [--help] [-o OFFSET] input output
positional arguments:
input Input file
output Output reconstructed PE
options:
-h, --help show this help message and exit
-o OFFSET, --offset OFFSET
Offset to real data, skip possible garbage
그러나 복호화된 코어 바이너리인 license.dat.decrypted에서 rebuild_pe.py를 사용하려고 하면 다음과 같은 오류 메시지가 표시됩니다:
python .\rebuild_pe.py .\extract\license.dat.decrypted .\extract\core.bin
Traceback (most recent call last):
File "rebuild_pe.py", line 32, in <module>
main()
File "rebuild_pe.py", line 28, in main
custom_pe.CustomPE(data).to_pe().write(args.output)
File "nightmare\malware\icedid\custom_pe.py", line 86, in __init__
raise RuntimeError("Failed to parse custom pe")
RuntimeError: Failed to parse custom pe
여기서 미묘한 점은 사용자 지정 PE 데이터가 항상 파일의 시작 부분에서 시작되는 것은 아니라는 점입니다. 이 경우 예를 들어 HxD와 같은 16진수 편집기에서 파일을 열면 실제 데이터보다 먼저 일정량의 가비지 바이트를 관찰할 수 있습니다.
저희 조사 결과 가비지 크기는 129바이트인 것으로 확인되었습니다.
이를 염두에 두고 가비지 바이트를 건너뛰고 "-o 129" 파라미터를 사용하여 rebuild_pe.py 스크립트를 사용하여 코어 바이너리를 다시 빌드할 수 있습니다. 이번에는 다행히도 오류 메시지가 표시되지 않았습니다. core.bin은 예제에서 추출한 출력 디렉터리에 저장됩니다.
python .\rebuild_pe.py .\extract\license.dat.decrypted .\extract\core.bin -o 129
재구축된 PE 오브젝트는 직접 실행할 수 없지만 원하는 디스어셈블러를 사용하여 정적으로 분석할 수 있습니다.
재구축된 바이너리 섹션에 사용자 지정 이름을 지정했습니다( .mare{0,1,2,...} ).
이 도구를 만드는 데 영감을 준 해시레자데의 작업에 감사를 표하고 싶습니다.
코어 바이너리 실행(Windows만 해당)
핵심 바이너리는 ICEDID의 사용자 지정 PE 형식과 엔트리 포인트 함수 프로토타입을 이해하는 사용자 지정 로더 없이는 실행할 수 없습니다.
연구 결과, 엔트리 포인트는 컨텍스트 구조라고 부르는 구조를 기대하며, 이 구조에는 암호화된 구성의 ICEDID 코어 및 지속성 로더 경로가 포함되어 있다는 것을 알고 있습니다. 컨텍스트 구조는 아래에 설명되어 있습니다.
기본적으로 코어 바이너리를 실행하기 위해 랩-리스\도구\아이디\gzip-variant\load_core.py 스크립트를 사용하지만, 이 스크립트를 사용하기 전에 이 구조를 구축하는 데 필요한 모든 정보가 포함된 context.json 파일을 만들어야 합니다.
이 샘플에서는 가짜 압축 파일에 포함된 정보를 복사하고 암호화된 구성 파일의 경로를 사용합니다. gzip_variant/context.json.example에 예제가 포함되어 있습니다.
샘플을 반전시키면서 "field_0 " 및 "stage_2_export " 값을 찾아야 한다는 점에 유의하세요.
여기서는 이전 연구의 값을 자리 표시자로 사용하지만 샘플이 100% 작동한다고 보장할 수는 없습니다. 예를 들어, 이 샘플에서는 1번 서수 내보내기가 지속성 로더의 실제 진입 지점인지 알 수 없습니다.
또한 UponBetter 디렉터리를 생성하고 license.dat 파일을 이 디렉터리로 이동하여 첫 번째 단계 동작을 재현합니다.
복호화된 코어 바이너리인 license.dat.decrypted, context.json 파일을 사용하여 labs-releases\tools\icedid\gzip_variant\load_core.py 스크립트를 실행합니다.
경고: 바이너리는 이 스크립트에 의해 기본적으로 로드/실행되며, Elastic Security Labs는 사용자 시스템에 대한 어떠한 손상도 책임지지 않습니다. 안전한 환경에서만 실행하세요.
usage: load_core.py [--help] [-o OFFSET] core_path ctx_path
positional arguments:
core_path Core custom PE
ctx_path Path to json file defining core's context
options:
-h, --help show this help message and exit
-o OFFSET, --offset OFFSET
Offset to real data, skip possible garbage
이전 섹션에서 설명한 것과 동일한 가비지 바이트 문제가 발생하므로 "-o 129" 매개 변수를 사용하여 가비지 바이트를 건너뜁니다.
python .\gzip-variant\load_core.py .\extract\license.dat.decrypted .\gzip-variant\context.example.json -o 129
============================================================
Core Loader
============================================================
Base address: 0x180000000
Entrypoint: 0x180001390
Press a key to call entrypoint...
스크립트가 실행되면 엔트리 포인트를 호출하기 전에 사용자 입력을 기다립니다. Python 프로세스에 디버거를 쉽게 연결하고 ICEDID 코어 진입점(이 예제에서는 0x180001390 )에 중단점을 설정할 수 있습니다.
키를 누르면 진입 지점에 도달합니다.
바이너리를 실행하면 다음 스크린샷에 표시된 것처럼 ICEDID 스레드가 생성되는 것을 볼 수 있습니다.
재빌드된 코어 바이너리에서 페이로드 언패킹 및 재빌드하기
코어 바이너리 내에 포함된 페이로드를 추출하기 위해, labs-releases\tools\icedid\gzip-variant\extract_payloads_from_core.py 스크립트를 사용하겠습니다.
usage: extract_payloads_from_core.py [--help] input output
positional arguments:
input Input file
output Output directory
options:
-h, --help show this help message and exit
이 스크립트를 재구축된 코어 바이너리에 사용하겠습니다.
python .\gzip-variant\extract_payloads_from_core.py .\extract\core.bin core_extract
core_extract\browser_hook_payload_0.cpe
core_extract\browser_hook_payload_1.cpe
여기에서 웹 브라우저 후킹 기능을 위한 ICEDID의 페이로드에 해당하는 두 개의 바이너리를 출력하지만, 여전히 사용자 정의 PE 형식입니다.
조사 결과, 브라우저 후크 페이로드의 x64 버전은 browser_hook_payload_0.cpe, x86 버전은 browser_hook_payload_1.cpe로 확인되었습니다.
이를 다시 빌드하기 위해 재빌드_pe.py 스크립트를 다시 사용하며, 이번에는 건너뛸 가비지 바이트가 없습니다.
python .\rebuild_pe.py .\core_extract\browser_hook_payload_0.cpe .\core_extract\browser_hook_payload_0.bin
python .\rebuild_pe.py .\core_extract\browser_hook_payload_1.cpe .\core_extract\browser_hook_payload_1.bin
이제 추가로 분석할 수 있는 두 개의 PE 바이너리( browser_hook_payload_0.bin 및 browser_hook_payload_1.bin )가 생겼습니다.
주의 깊은 독자라면 코어 바이너리에서 VNC 서버 언패킹을 생략한 것을 눈치챌 수 있는데, 이는 의도적으로 내린 결정입니다. 향후 연구에서 다른 도구와 함께 공개할 예정이니 기대해 주세요!
결론
이 튜토리얼에서는 가짜 GZip 바이너리 추출부터 시작하여 코어 바이너리를 재구성하고 페이로드를 언패킹하는 ICEDID GZip 변종 언패킹을 다뤘습니다.
ICEDID는 지속적으로 진화하고 있으며, 주요 변경 사항을 지속적으로 모니터링하고 연구와 함께 툴을 업데이트할 예정입니다. 문제가 발생하거나 예상대로 작동하지 않는 경우 언제든지 문제를 제기하거나 메시지를 보내주세요.
Elastic Security Labs는 세부적인 탐지 로직, 보호 기능, 응용 위협 연구 발표를 통해 공격자를 방해하는 데 주력하는 전담 연구원과 보안 엔지니어들로 구성된 팀입니다.
elasticseclabs를 팔로우하고연구 포털을 방문하여 더 많은 리소스와 연구를 확인하세요.
참고 자료
위의 조사에서 참조한 내용은 다음과 같습니다:
- https://www.elastic.co/pdf/elastic-security-labs-thawing-the-permafrost-of-icedid.pdf
- https://securityintelligence.com/new-banking-trojan-icedid-discovered-by-ibm-x-force-research/
- https://www.justice.gov/opa/pr/emotet-botnet-disrupted-international-cyber-operation
- https://malpedia.caad.fkie.fraunhofer.de/details/win.darkvnc
- https://www.cybereason.com/blog/threat-analysis-report-all-paths-lead-to-cobalt-strike-icedid-emotet-and-qbot
- https://github.com/elastic/labs-releases
- https://github.com/hasherezade/funky_malware_formats/blob/f1cacba4ee347601dceacda04e4de8c699971d29/iced_id_parser/iceid_to_pe.cpp
- https://mh-nexus.de/en/hxd/
- https://hex-rays.com/IDA-pro/