赞
踩
IPC(Inter-Process Communication),含义为进程间通信或者跨进程通信,指至少两个进程或线程间传送数据或信号的一些技术或方法。进程是计算机系统分配资源的最小单位(进程是分配资源最小的单位,而线程是调度的最小单位,线程共用进程资源)。每个进程都有自己的一部分独立的系统资源,彼此是隔离的。为了能使不同的进程互相访问资源并进行协调工作,才有了进程间通信。
任何一个操作系统都需要有相应的IPC机制,比如Windows上可以通过剪贴板、管道和邮槽等来进行进程间通信,而Linux上可以通过命名共享内容、信号量等来进行线程间通信。
通常在渗透测试情况下,我们所说的 IPC 主要针对的是windows中的IPC
默认情况下,IPC是Windows中的一个默认共享资源,代表IPC服务。它通常用于管理目的,如远程管理计算机。默认情况下,IPC 共享被创建,但不允许匿名访问,这意味着只有具有适当凭据的用户才能使用 IPC$ 进行通信。
net use \\[:host]\IPC$ [: password] /user:[: username]
net use \\[:host]\IPC$ /del
适用于: Windows 7、Windows Server 2003、Windows Server 2008、Windows Server 2008 R2、Windows Vista、Windows XP
空链接就是不用密码和用户名的IPC连接。空会话是在没有信任的情况下与服务器建立的会话(即未提供用户名与密码),但根据 WIN2000 的访问控制模型,空会话的建立同样需要提供一个令牌,但这并不表示空会话的令牌中不包含 安全标识符SID (它标识了用户和所属组),对于一个空会话, LSA 提供的令牌的 SID 是 S- 1-5-7 ,这就是空会话的 SID ,用户名是: ANONYMOUS LOGON (这个用户名是可以在用户列表中看到的,但是不能在 SAM 数据库中找到,属于系统内置的帐号)
ANONYMOUS LOGON是指一种网络访问类型,用户无需提供任何身份验证凭据(例如用户名或密码)即可登录系统或网络资源,在Windows中作为一个内置安全主体出现。它主要代表匿名登陆的用户,例如Guest用户。它的全名是:NT AUTHORITY\ANONYMOUS LOGON。
NT Authority 是各种预定义的、特殊用途的 Windows 帐户和组的名称,它们是操作系统功能的一部分,允许核心操作系统服务和功能发挥作用。它们促进资源访问并控制 Windows 系统内的安全边界。
当您在权限或访问控制列表 (ACL) 上下文中看到“NT Authority”时,通常表示权限或特权被授予系统级实体而不是特定用户或组。例如,“NT Authority\SYSTEM”指的是本地系统帐户,该帐户对系统具有较高的权限。
一些常见的 NT Authority 安全原则包括:
net use \\[: hostname] “” /user:“”
net use \\[: hostname] /user:“” “”
net view \\ip
此命令不能显示默认共享(IPC 、 A d m i n 、Admin 、Admin、盘符共享)
net time \\ip
nbtstat -A ip
关于这章节的内容IPC横向、Hash传递等将会在后续章节、文章中慢慢为补充
dir \\[: hostname]\path
copy [: local_path] \\[: hostname]\[: remote_path]
copy \\[: hostname]\[: remote_path] [: local_path]
type \\[: hostname]\[: remote_file_path]
在windows上除了上述的 IPC 共享,还有默认共享和普通共享,他们之间又有什么不一样的呢?
ADMIN$
(表示系统管理员目录),C$
、D$
等(分别对应于系统上的C盘、D盘等驱动器) IPC连接在Windows系统中用于进程间通信,它涉及到文件和打印服务共享。在IPC连接过程中,Windows系统会记录一些安全事件日志,这些日志具有特定的事件ID,每个ID代表不同的操作或状态。以下是一些常见的与IPC连接相关的Windows日志事件ID及其含义:
psexec 是一个命令行工具,它使用 Windows 的 SMB (Server Message Block) 协议来执行远程命令。SMB 协议主要用于文件共享和打印服务,但也提供了运行远程系统上的程序的能力。
当您使用 PsExec 连接到远程计算机时,它首先会在远程计算机上创建一个名为 PSEXESVC 的服务。
(以下将会以数据包的方式生动形象的解释整个连接过程)
首先会向目标主机发送TCP三次握手数据包尝试创建连接,如果目标主机拒绝连接或者不在线,则TCP连接失败,退出程序。
接下来需要协商通信协议版本,PsExec 利用的协议主要是SMB协议。SMB(全称是Server MessageBlock)是一个协议名,可用于在计算机间共享文件、打印机、串口等,电脑上的网上邻居就是靠它实现的,SMB工作原理如下:攻击机向目标机器发送一个SMB negotiate protocol request请求数据包,并列出它所支持的所有SMB协议版本(其中Dialect带有一串16进制的code对应着SMB的不同版本以此分辨准确版本),若无可使用的版本返回0XFFFFH结束通信。
目标机器返回NEGTIATE ResponseDialect数据包协商确定使用SMB2.1,至此SMB协商使用SMBv2协议通信过程结束。
协商完 SMB 版本过后,就是NTLM身份认证开始,攻击机向目标机器发送SESSION_SETUP_ANDX协商请求,以完成攻击机与目标机器之间的身份验证,该请求包含用户名密码。
成功通过NTLM身份认证后,攻击机向目标机器发送Tree connect rerquest SMB数据包,并列出想访问网络资源的名称ipc 、 a d m i n 、admin 、admin,目标机器返回tree connect response响应数据包表示此次连接是否被接受或拒绝
连接到相应资源后,通过 SMB 访问默认共享文件夹ADMIN$,写入PSEXESVC.exe文件。路径为 C:\windows\System32\PSEXESVC.exe
注意1:C:\windows\System32\PSEXESVC.exe 是微软官方工具默认设定的,一般情况下无法修改
close request and response 数据包表示PSEXESVC.exe文件完成写入。
接着查看openservicew request的数据包,发现攻击机开始远程调用svcctl协议并打开psexesvc服务(psexec必须调用svcctl协议,否则psexesvc服务无法启动)。
在完成文件上传之后依次使用OpenSCManagerW、OpenServicceW、StartServiceW方法来创建启动服务。
\.\pipe
:这是系统级管道的根目录,包含了许多系统服务和进程使用的命名管道。例如,.\pipe\lsass是Local Security Authority Subsystem Service(LSASS)使用的管道.\pipe\lsass
:用于与本地安全子系统(Local Security Authority SubsystemService,LSASS)通信,LSASS负责处理登录认证、密码策略等安全相关的功能,SMB流量中会经常看见和lsass协议服务通信的流量.\pipe\winreg
:用于与Windows注册表服务(Windows Registry Service)通信,允许应用程序访问和操作系统的注册表,SMB流量中会经常看见和lsass协议服务通信的流量.\pipe\svcctl
:用于与服务控制管理器(Service Control Manager)通信,允许应用程序创建、修改和管理系统服务,SMB流量中会经常看见和svcctl协议服务通信的流量用来远程启动应用和服务.\pipe\browser
:用于与计算机浏览器服务(Computer Browser Service)通信,负责在网络上发现和维护共享资源列,SMB流量中会经常看见和browser协议服务通信的流量.\pipe\epmapper
:用于与终结点映射器(Endpoint Mapper)通信,EPMapper服务负责映射RPC终结点标识符(RPC Endpoint Identifiers,EPI)到网络地址和端口号,SMB流量中会经常看见和epmapper协议服务通信的流量 后续创建了psexesvc、stdin、stdout、stderr 4个命名管道。用于对程序标准输入流、标准输出流、错误数据流进行重定向。
管道创建成功后,psexec可以正常使用,已成功连上目标机器cmd。
在连接过程中,攻击机会每隔30s向目标机器发送一次TCP-keep-alive数据包,保持TCP心跳连接。
退出远程连接时,tcp四次挥手关闭连接,psexesvc、stdin、stdout、stderr4个管道也会关闭,会话结束。
GetComputerNameW 函数来提取本地计算机的 NetBIOS 名称
LookupPrivilegeValue 函数检索指定系统上用于本地表示指定特权名称 (LUID) 本地唯一标识符
如果能够IPC链接,那么就使用CreateRestrictedToken 创建一个新的访问令牌
具体和远端身份校验的时候是在后面 使用 WNetAddConnection2W API 与远程计算机上的 IPC$ 共享建立连接
的时候,这里只是简单接解析一下用到的函数
可执行文件通过调用 CreateEventW API 创建一个未命名的事件对象
并使用SetConsoleCtrlHandler将一个新函数添加到当前进程的处理函数列表中
显示一条中间消息,提供有关接下来将发生的操作的详细信息(这些消息在正常执行期间几乎看不见,以为每个阶段运行完后控制台数据流缓冲区都会被刷新)
使用 WNetAddConnection2W API 与远程计算机上的 IPC$ 共享建立连接。
使用 FindResourceW 函数调用来确定名为 PSEXESVC.EXE
资源路径,将资源加载到内存中,并通过调用以下函数检索指向内存中指定资源的指针:LoadResource、SizeofResource 和 LockResource
使用 WNetAddConnection2W API 对远程计算机上的 admin$ 共享资源文件进行访问
尝试写入远程计算机上的 系统文件共享路径写入 PSEXESVC.EXE (\\\\192.168.75.133\\ADMIN$\\PSEXESVC.EXE)
清空原本控制台的连接信息
清空控制台缓存内容,打印新的字符
创建 PSEXESVC服务,通过调用 OpenSCManagerW 例程 (0xF003F = SC_MANAGER_ALL_ACCESS ) 建立与远程计算机上的服务控制管理器的连接
并远程主机上的进程创建了一个名为“PSEXESVC”的新服务(0xF01FF = SERVICE_ALL_ACCESS、0x10 = SERVICE_WIN32_OWN_PROCESS、0x3 = SERVICE_DEMAND_START):
自系统启动以来经过的毫秒数通过对 GetTickCount 的函数调用来提取
使用 OpenServiceW 获取 PSEXESVC 系统服务句柄
再使用 StartServiceW 启动 PSEXESVC服务
并在远端通过调用 QueryServiceStatus 来查看 PSEXESVC 服务的当前状态
会向远端admin$目录写入文件
可以在目标机器上看到对应文件(%systemroot%\PSEXEC-WIN-***-.key)
这个文件只能在 system 以上权限下才能查看
PsExec.EXE 从远程计算机打开 \pipe\PSEXESVC 管道,并通过调用 SetNamedPipeHandleState API 来修改管道模式(0x2 = PIPE_READMODE_MESSAGE)
根据文献[9]所述,出现了一部分间接调用用于程序方法初始化部分数据及方法,RtlInitUnicodeString函数用于初始化“\Device\LanmanRedirector<计算机名\IP地址>\ipc$”Unicode字符串,但是在新版(我当前测试版本v2.43)的程序中,已经修改成了使用call方法直接调用
PSEXEC.EXE 使用 NtOpenFile 打开 \\192.168.75.133\ipc$
共享(0x100001 = FILE_READ_DATA | SYNCHRONIZE、0x1 = FILE_SHARE_READ、0x90 = FILE_SYNCHRONOUS_IO_ALERT | FILE_CREATE_TREE_CONNECTION)
PsExec 通过调用 NtFsControlFile 函数并使用特定的控制代码 0x1401a3 = FSCTL_NETWORK_GET_CONNECTION_INFO来获取连接信息
__kernel_entry NTSYSCALLAPI NTSTATUS NtFsControlFile(
[in] HANDLE FileHandle,
[in, optional] HANDLE Event,
[in, optional] PIO_APC_ROUTINE ApcRoutine,
[in, optional] PVOID ApcContext,
[out] PIO_STATUS_BLOCK IoStatusBlock,
[in] ULONG FsControlCode,
[in, optional] PVOID InputBuffer,
[in] ULONG InputBufferLength,
[out, optional] PVOID OutputBuffer,
[in] ULONG OutputBufferLength
);
第二次调用 NtFsControlFile 发送另一个控制代码 0x1401AC = FSCTL_NETWORK_DELETE_CONNECTION
而后又分别建立了 stdin、 stdout、 stderr 三个信道
PsExec 等待 stdin
管道返回可供连接的实例,管道和其他对应于标准输出\错误的管道是由远程主机上启动的 PSEXESVC 进程创建的。
使用 CreateFileW 打开上述命名管道
用 GetVersion API 检索操作系统的主要版本号和次要版本号
之后将会把之前生成的 .key
文件删除
通过调用 CryptAcquireContextW (0x18 = PROV_RSA_AES ) 获取特定 CSP(加密服务提供商)内密钥容器的句柄
CryptCreateHash 用于创建哈希对象(0x8004 = CALG_SHA1)
AES256 密钥是使用 CryptDeriveKey (0x6610 = CALG_AES_256) ,这是一种从 SHA1 哈希算法派生而来
创建名为 Global\PSEXESVC-<计算机名称\IP 地址>-<进程 ID>
的事件对象
数据缓冲区中使用AES256算法进行加密
使用WriteFile API 用于从管道写入加密后数据
ReadFile API 用于从管道读取加密数据,再通过调用 CryptDecrypt 使用 AES 算法对缓冲区进行解密
进程标识符是通过调用 GetCurrentProcessId 函数获得的
并通过进程标识符创建名为“Global\PSEXESVC-<计算机名称\IP 地址>-<进程 ID>”的事件对象
CreateThread API 用于创建两个线程,最终将执行 处理标准错误函数 和 处理标准输入函数(0x4 = CREATE_SUSPENDED)
使用 DuplicateHandle (0x10000000 = GENERIC_ALL)复制线程句柄
使用 SetConsoleTitleW 更改控制台窗口的标题,并使用WaitForMultipleObjects 函数,以挂起进程,直到上述线程完成并且上面创建的事件对象处于有信号状态
使用 SetEvent 将事件对象设置为有信号状态
第二次调用 WaitForMultipleObjects 会挂起进程,直到上述两个线程完成
线程通过调用 GetStdHandle 例程获取标准输入设备的句柄,调用 WaitForSingleObject 函数来检查事件对象是否处于有信号状态,如果有输入数据流传递过来,使用 ReadConsoleW 函数从控制台输入缓冲区挨个读取字符
管道实例的服务器端使用 DisconnectNamedPipe 与进程断开连接
处理标准错误的逻辑与处理标准输入的差不多,就不展开了
(这里我以处理 whoami 结果为例)
使用 ReadFile API 用于从 stdin 管道读取加密数据
ReadFile API 用于从上述管道读取加密数据
通过调用 CryptDecrypt 使用 AES 算法对缓冲区进行解密
MultiByteToWideChar 用于将字符串映射到 UTF-16(宽字符)字符串
使用 GetStdHandle (0xFFFFFFF5 = STD_OUTPUT_HANDLE )检索标准输出设备的句柄
上面解密的缓冲区通过调用 WriteFile 写入标准输出
具体流程如下所示
使用cryptReleaseContext在程序完成 CSP 的使用后调用此函数,释放的 CSP 句柄,令其不再有效
继续调用cryptDestroyKey函数将 CSP 引用会话密钥,或已导入加密服务提供程序(CSP) 通过 CryptImportKey的公钥销毁密钥,并释放该密钥使用的内存
删除PSEXESVC服务相关信息
DeleteFileW 用于删除之前创建的 PSEXESVC.exe 文件
WNetCancelConnection2W API 用于取消现有的网络连接(IPC$)
会尝试删除 .key 文件,因为 .key 文件会在管道正确建立后被删除,但是如果出现不可知情况的话,在退出程序后将会尝试删除这个文件
在当前测试环境中,目标对象防火墙策略开启,流量被拦截
因为是 Connection error 由于连接方在一段时间后没有正确答复或连接的主机没有反应
,建立连接过程超时,在排除网络不稳定的可能性外,所以怀疑是流量不放通
所有的结局方案我都是尽量通过命令行完成,因为在渗透环境中获取到一个临时会话还是容易的
关闭服务器防火墙后成功获取shell
(1.2.1.1 - 1.2.1.4 针对的是 windows version 7 及以上高版本windows)
netsh advfirewall set domainprofile state off
netsh advfirewall set domainprofile state on
netsh advfirewall set privateprofile state off
netsh advfirewall set privateprofile state on
netsh advfirewall set publicprofile state off
netsh advfirewall set publicprofile state on
netsh advfirewall set allprofiles state off
netsh advfirewall set allprofiles state on
(1.2.1.5 针对较旧的Windows版本 – XP / Server 2003)
netsh firewall set opmode mode=DISABLE
netsh firewall set opmode mode=ENABLE
直接关闭防火墙的话动静太大了,在可以的情况下我们应尝试缩小动作影响范围(通常设置规则需要管理员权限)
netsh advfirewall firewall add rule name="规则名称" dir=in action=allow protocol=TCP localport=端口号
例如在这里我们建立入站规则 PsExec
:尝试放通445端口,允许445端口流量入站
netsh advfirewall firewall add rule name="PsExec" dir=in action=allow protocol=TCP localport=445
netsh advfirewall firewall add rule name="规则名称" dir=in action=allow program="程序路径" enable=yes
如果想添加的是出站规则,只需将 dir=in
改为 dir=out
即可
netsh advfirewall firewall add rule name="规则名称" dir=out action=allow protocol=TCP localport=端口号
netsh advfirewall firewall add rule name="规则名称" dir=out action=allow program="程序路径" enable=yes
netsh advfirewall firewall show rule name=all
在当前测试环境中,这个建立链接的过程,我们可以看到,authentication
认证过程出现了问题
使用 gpedit.msc
打开组策略编辑器,我们在本地计算机 策略
-> 计算机配置
-> Windows 设置
-> 安全设置
-> 账号策略
-> 密码策略
中可以看到其中有一项策略:
密码必须符合复杂性要求
这条策略迫使我们的用户密码需要一定的强度。
但是可能在真实渗透环境中,本地主机用户中就存在空密码或者弱密码用户
[Unicode]
Unicode=yes
[Version]
signature="$CHICAGO$"
Revision=1
[System Access]
PasswordComplexity = 0
MinimumPasswordLength = 0
PasswordHistorySize = 0
PasswordComplexity = 0 关闭密码复杂度
MinimumPasswordLength = 0 允许空密码
secedit /configure /db %windir%\security\local.sdb /cfg [: 修改后的配置文件在远程主机的位置] /areas SECURITYPOLICY
gpupdate /force
使用 impacket.py 进行横向时可以发现当前用户对 Admin$
和 C$
共享文件路径并没有写权限
而如果直接使用 PsExec.exe 建立连接则会提示远端拒绝连接
共享文件夹仅对部分组成员进行写权限的开放,当前用户权限过低,无法向目标文件夹写入文件。
net share
icacls “文件路径”
在上述 ACL 矩阵中可以看到本地管理员权限对默认共享文件有 Full 权限(Read权限和 Write 权限),查看本地管理员组用户
net localgroup administrators
发现本地计算机管理员组用户里不存在我们的Mike(测试账号)用户
尝试将 Mike 加入管理员组,成功 PsExec 获取 shell
关于什么是 LocalAccountTokenFilterPolicy 将会在下一个部分展开讲解,这里我们只简略说明
reg query "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System" /v LocalAccountTokenFilterPolicy
可以看到这里的表项数值为0,有些计算机上可能也不存在这条表项,使用下面的语句修改/添加该表项
reg add "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System" /v LocalAccountTokenFilterPolicy /t reg_dword /d 1 /f
net start LanmanServer
net share
可以看到当前主机并不开放默认共享的文件夹,这是我们可以手动尝试开启
reg add "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\LanmanServer\Parameters" /v AutoShareServer /t reg_dword /d 1 /f
注意1:部分表项属于系统预定义表项,可以不再注册表中显示
注意2: 修改完服务相关配置后,需要重启服务或者重启计算机才能够使得配置生效
在尝试建立 IPC 通信时发生错误
发生系统错误 384。
因为文件共享不安全,所以你不能连接到文件共享。此共享需要过时的 SMB1 协议,而此协议是不安全的,可能会使你的系统遭受攻击 。
你的系统需要 SMB2 或更高版本。有关如何解决此问题的信息,请参见: https://go.microsoft.com/fwlink/?linkid=852747
微软已经宣布 SMB1 将不再被支持,并且在未来的 Windows 版本中可能会被完全移除
Get-WindowsOptionalFeature -Online -FeatureName SMB1Protocol
如果 SMB1 已经安装,但是禁用状态,可以使用以下命令启用(但是会重启客户端系统)
Enable-WindowsOptionalFeature -Online -FeatureName SMB1Protocol
[1] https://blog.csdn.net/no1xium/article/details/107358939
[2] https://learn.microsoft.com/zh-cn/sysinternals/downloads/psexec
[3] https://blog.csdn.net/weixin_41101173/article/details/79868887
[4] https://upimg.baike.so.com/doc/3974871-27398037.html
[5] https://blog.csdn.net/qq_45521281/article/details/105820827
[6] https://www.calcomsoftware.com/nt-authority-anonymous-logon/
[7] https://mp.weixin.qq.com/s/BZPc8J2_2_SjwX0nepkXLQ
[8] https://blog.csdn.net/javajiawei/article/details/138700056
[9] https://cybergeeks.tech/reverse-engineering-psexec-for-fun-and-knowledge/
[10] https://learn.microsoft.com/zh-cn/windows/win32/api/@[toc]
关注我们,咱们在安全的路上,扬帆起航
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。