• 黑帽python第二版(Black Hat Python 2nd Edition)读书笔记 之 第十章 Windows提权(1)进程监视器


    黑帽python第二版(Black Hat Python 2nd Edition)读书笔记 之 第十章 Windows提权(1)进程监视器



    写在前面

    假设我们已经在一个Windows网络中,也许我们是利用了远程堆溢出,或者网络钓鱼等方式进入的。现在是时候寻找提升特权的方法了。
    即使我们已经以SYSTEM或Administrator的身份运行,我们也可能希望通过多种方式获得这些特权,以防周期性的补丁程序终止我们的访问。因此在你的手中有一个特权等级目录也很重要,因为有些企业运行的软件在我们自己的环境中可能很难分析,而且我们可能只有在一个相同规模或组成的企业中才能运行这类软件。
    在典型的提权过程中,我们可能会利用编码错误的驱动程序或本机Windows的内核问题,但如果我们使用低质量的漏洞或在利用过程中出现问题,则可能会导致系统不稳定。现在让我们探索一下在Windows上提权的其他方法。大型企业中的系统管理员通常会安排执行子进程的任务或服务,或运行VBScript或PowerShell脚本以自动化某些活动;设备供应商也经常有自动的、内置的任务,它们的行为方式都是一样的。我们将尝试利用任何处理文件或执行可由低权限用户写入的二进制文件的高权限进程。有无数种方法可供我们尝试提升Windows上的权限,我们将仅介绍其中的几种。但是,当我们理解了这些核心概念后,我们可以扩展脚本,以探索Windows目标的其他黑暗的、发霉的角落。
    我们将从“学习如何应用Windows Management Instrumentation(WMI)编程来创建一个灵活的界面来监控新进程的创建”开始。我们将获取有用的数据,例如文件路径、创建进程的用户和启用的权限。然后,我们将把所有文件路径交给一个文件监控脚本,该脚本持续跟踪创建的任何新文件,以及写入其中的内容。这告诉我们高权限进程正在访问哪些文件。最后,我们将通过将自己的脚本代码注入文件中来拦截文件创建过程,并使高权限进程执行注入的代码。整个过程的美妙之处在于它不涉及任何API挂钩,因此我们可以在大多数防病毒软件

    安装依赖

    我们需要安装一些库来编写本章中的工具。先在windows上的cmd.exe中执行以下的shell:

    > pip install pywin32 wmi pyinstaller
    
    • 1

    这个安装执行的很顺利,不赘述。当我们在第8章制作键盘记录器和屏幕截图时,我们可能已经安装了pyinstaller,如果没有的话现在就安装一下。接下来,我们将创建用于测试监控脚本的示例服务。

    创建有脆弱性的服务

    我们正在创建的服务模拟了大型企业网络中常见的一组漏洞(我们将会在本章的晚些时候讨论它们),此服务将定期将脚本复制到临时目录并从该目录执行。创建并打开bhservice.py脚本,然后输入下面的代码:

    import os
    import serviccemanager
    import shutil
    import subprocess
    import sys
    
    import win32event
    import win32service
    import win32serviceutil
    
    SRCDIR = 'C:\\Users\\lpx\\work'
    TGTDIR = 'C:\\Windows\\TEMP'
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    我们先进行导入,设置脚本文件的源目录,然后设置服务将运行它的目标目录。现在,我们将使用一个类创建实际的服务:

    class BHServerSvc(win32serviceutil.ServiceFramework):
        _svc_name_ = 'BlackHatService'
        _svc_display_name = 'Black Hat Service'
        _svc_description_ = ("Executes VBScripts at regular intervals." + " What could possibly go wrong?")
    
        def __init__(self, args):
            self.vbs = os.path.join(TGTDIR, 'bhservice_task.vbs')
            self.timeout = 1000 * 60
    
            win32serviceutil.ServiceFramework.__init__(self, args)
            self.hWaitStop = win32event.CreateEvent(None, 0, 0, None)
        
        def SvcStop(self):
            self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING)
            win32event.SetEvent(self.hWaitStop)
        
        def SvcDoRun(self):
            self.ReportServiceStatus(win32service.SERVICE_RUNNING)
            self.main()
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    这个类是任何服务必须提供的内容的骨架。它继承自win32serviceutil.ServiceFramework并定义了三个方法:在__init__方法中,我们初始化框架,定义要运行的脚本的位置,设置一分钟的超时,并创建事件对象;在SvcStop方法中,我们设置服务状态并停止服务;在SvcDoRun方法中,我们启动服务并调用任务将在其中运行的main方法。接下来我们定义这个main方法:

        def main(self):
            while True:
                ret_code = win32event.WaitForSingleObject(self.hWaitStop, self.timeout)
                if ret_code == win32event.WAIT_OBJECT_0:
                    serviccemanager.LogInfoMsg("Service is stopping")
                    break
                src = os.path.join(SRCDIR, 'bhservice_task.vbs')
                shutil.copy(src, self.vbs)
                subprocess.call("cscript.exe %s" % self.vbs, shell=False)
                os.unlink(self.vbs)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    基本上,我们建立了一个每分钟运行一次的循环,这是由于self.timeout参数,直到服务接收到停止信号。当它运行时,我们将脚本文件复制到目标目录,执行脚本并删除该文件。
    在main主块中,我们处理任何的命令行参数:

    if __name__ == '__main__':
        if len(sys.argv) == 1:
            serviccemanager.Initialize()
            serviccemanager.PrepareToHostSingle(BHServerSvc)
            serviccemanager.StartServiceCtrlDispatcher()
        else:
            win32serviceutil.HandleCommandLine(BHServerSvc)
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    有时,我们可能希望在受害者计算机上创建真正的服务。这个框架为我们提供了如何构建一个服务框架的概要。
    另外,我们可以从https://nostarch.com/black-hat-python2E/站点找到bhservice_tasksvbs脚本。将文件放在bhservice py脚本中的SRCDIR指向的目录。我们的目录应该长得如下所示:
    在这里插入图片描述
    现在使用pyinstaller创建服务可执行文件,如果提示“‘pyinstaller’不是内部或外部命令…”,请把pyinstaller.exe文件所在的目录添加到windows的path环境变量,然后重新执行即可。

    > pyinstaller -F --hiddenimport win32timezone bhservice.py
    
    • 1

    运行结束后,会有类似如下的信息提示。
    在这里插入图片描述
    此命令保存bhservice.exe文件到dist子目录中,接下来我们切换到该目录来安装并启动服务。以管理员权限(一定要以管理员权限,否则后面start的时候会报拒绝访问)运行以下命令:

    > .\bhservice.exe install
    
    • 1

    执行结果如下图所示。
    在这里插入图片描述

    > .\bhservice.exe start
    
    • 1

    执行start任务,如下图所示。
    在这里插入图片描述
    顺便说明一下,如果将来需要删除服务的时候,直接用remove命令即可,如下图。
    在这里插入图片描述
    现在,我们启动的服务每分钟都会将脚本文件写入一个临时目录,执行脚本并删除该文件。它将执行此操作,直到我们运行stop命令:
    在这里插入图片描述
    我们可以随时启动或停止服务。请记住,如果我们更改bhservice.py中的代码,我们还必须使用pyinstaller创建一个新的可执行文件,并让Windows使用bhservice update命令重新加载服务。完成本章中的服务后,请使用bhservice remove将其删除。

    创建进程监视器

    几年前,这本书的作者之一Justin为安全提供商Immunity的项目El Jefe做出了贡献。El Jefe的核心是一个非常简单的过程监控系统。该工具旨在帮助防御团队中的人员跟踪进程创建和恶意软件的安装。
    有一天,他的同事马克·沃格勒(Mark Wuergler)在咨询时建议他们更具有攻击性地使用El Jefe:通过它,他们可以监控目标Windows机器上作为SYSTEM执行的进程。这将深入了解潜在的不安全文件处理或子进程创建。这起了作用,他们找到了无数特权升级漏洞。
    原始El Jefe的主要缺点是它使用了一个DLL,注入到每个进程中,以拦截对本地CreateProcess函数的调用。然后,它使用命名管道与收集客户端通信,收集客户端将进程创建的详细信息转发给日志服务器。不幸的是,大多数防病毒软件也会钩住CreateProcess调用,因此他们要么将您视为恶意软件,要么在与防病毒软件并行运行El Jefe时出现系统不稳定问题
    我们将以无钩的方式重新创建El Jefe的一些监控能力,使其适应进攻技术。这将使我们的监控具有便携性,并使我们能够无问题地与防病毒软件一起运行。

    通过WMI监控进程

    Windows Management Instrumentation(WMI)API使程序员能够监视系统中的某些事件,然后在这些事件发生时接收回调。我们将利用此接口在每次创建进程时接收回调,然后记录一些有价值的信息:创建进程的时间、生成进程的用户、启动的可执行文件及其命令行参数、进程ID和父进程ID,调用外部文件(如VBScript或批处理脚本)的任何进程。当我们掌握了所有这些信息后,我们还将确定在进程令牌上启用的特权。在某些罕见的情况下,我们会发现作为普通用户创建的进程,但已被授予我们可以利用的其他Windows权限。

    process_monitor.py脚本

    我们从编写一个非常简单的监控脚本开始,该脚本提供进程的基本信息,然后在此基础上构建确定启用的权限。请注意,为了捕获有关SYSTEM创建的高权限进程的信息,我们需要以管理员身份运行监控脚本。新建并打开process_monitor.py脚本,将以下代码添加进去:

    import os
    import sys
    from xml.dom.pulldom import PROCESSING_INSTRUCTION
    import win32api
    import win32con
    import win32security
    import wmi
    
    def log_to_file(message):
        with open('process_monitor_log.csv', 'a') as fd:
            fd.write(f'{message}\r\n')
    
    def monitor():
        head = 'CommandLine, Time, Executable, Parent PID, PID, User, Privileges'
        log_to_file(head)
        c = wmi.WMI()
        process_watcher = c.Win32_Process.watch_for('creation')
        while True:
            try:
                new_process = process_watcher()
                cmdline = new_process.CommandLine
                create_date = new_process.CreationDate
                executable = new_process.ExecutablePath
                parent_pid = new_process.ParentProcessId
                pid = new_process.ProcessId
                proc_owner = new_process.GetOwner()
    
                privileges = 'N/A'
                process_log_message = (
                    f'{cmdline}, {create_date}, {executable},'
                    f'{parent_pid}, {pid}, {proc_owner}, {privileges}'
                )
                print(process_log_message)
            except Exception:
                pass
    if __name__ == '__main__':
        monitor()
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38

    我们首先实例化WMI类,并告诉它监视进程创建事件。然后我们进入一个循环,该循环将一直阻塞,直到process_watcher返回一个新的进程事件。新的进程事件是一个名为Win32_process的WMI类,它包含我们正在寻找的所有相关信息。其中的一个类函数是GetOwner,我们调用它来确定是谁创建了进程。我们收集我们正在寻找的所有进程信息,将其输出到屏幕,并将其记录到文件中。

    小试牛刀

    让我们启动流程监控脚本并创建一些进程,看看输出是什么样子的:

    > python .\process_monitor.py
    
    • 1

    输入内容如下图所示,跟预期结果一致。
    在这里插入图片描述
    运行脚本后,我们运行了计算器等程序,该工具正确地输出了该进程的信息。我们可以让这个脚本运行一天,并捕获所有正在运行的进程、计划任务和各种软件更新程序的记录。如果运气不好,我们可能会发现恶意软件。登录和退出系统也很有用,因为这些操作生成的事件可能指示特权进程。

  • 相关阅读:
    MeterSphere专题之: 配套的浏览器插件:chrome-extensions
    ArrayList与LinkedList区别
    GMS之Launcher中去除默认Search或替换为Chrome Search
    【数据结构】面试OJ题——时间复杂度
    前端面试题:
    HDFS系统权限详解
    入门力扣自学笔记147 C++ (题目编号1598)
    阿里P7,一个女测试经理的成长之路
    解决导入maven工程时cannot resolve依赖问题
    git相关知识记录
  • 原文地址:https://blog.csdn.net/lipeixinglive/article/details/127525409