描述
- 登录目标机器后,需要获取system权限,可选择方式有攻击驱动程序或者系统内核,较难且容易导致系统奔溃,考虑到某些高权限任务所依赖的文件或者程序可以被低权限用户修改,如果在里面嵌入恶意代码,可以实现提权
- 本实验分为三个部分,首先模拟受害服务,该具有system权限的服务依赖vbs脚本,然后利用WMI编写进程监控程序,用于在目标机器上发现该受害服务,最后利用win32 api编写文件监控程序,获取篡改vbs脚本的时机,并嵌入恶意代码,实现提权
模拟受害服务
功能
- 该受害服务周期性地将脚本复制到某个临时目录,然后在该目录中执行脚本,之后删除脚本
代码
import os
from time import sleep
import servicemanager
import shutil
import subprocess
import sys
import win32event
import win32service
import win32serviceutil
SRCDIR = 'E:\\Project\\Python\\blackhat\\privilage'
TGTDIR = "C:\\Windows\Temp"
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*10
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()
def main(self):
while True:
ret_code = win32event.WaitForSingleObject(self.hWaitStop, self.timeout)
if ret_code == win32event.WAIT_OBJECT_0:
servicemanager.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)
if __name__ == "__main__":
if len(sys.argv) == 1:
servicemanager.Initialize()
servicemanager.PrepareToHostSingle(BHServerSvc)
servicemanager.StartServiceCtrlDispatcher()
else:
win32serviceutil.HandleCommandLine(BHServerSvc)
测试
- 用pyinstaller打包,注意需要添加隐式导入
pyinstaller -F --hiddenimport win32timezone service.py
- 部署服务
# 安装
service.exe install
# 运行
service.exe start
# 停止
service.exe stop
# 删除,实测还需要删除注册表中的服务项,并重启后服务才能被彻底删除
service.exe remove
- 安装服务后的截图
进程监控程序
预先知识
- WMI(Windows管理规范)接口能够帮助我们监控程序中的特定时间,并且在事件发生时收到系统的回调
- Windows系统的令牌权限:系统内核给每个进程授予了一个token,用于标注一个进程或线程可以执行什么样的任务,具有什么样的权限,比较重要的权限有
SetBackupPrivilege(允许读取任意文件)
、SetDebugPrivilege(允许将dll或代码注入其它进程)
和setLoadDriver(允许进程加载或卸载驱动程序)
功能
- 利用WMI接口监控进程的创建,打印出进程的用户、权限、令牌、依赖的脚本路径等重要信息,找出那些具有system权限,拥有重要令牌,并且依赖普通文件的进程
代码
- 获取进程令牌权限时,先查看权限是否被启用,然后再根据权限ID去查权限名称
import os
import sys
import win32api
import win32con
import win32security
import wmi
def log2file(message):
with open("monitor_process_log.csv", "a") as fd:
fd.write(f"{message}\r\n")
def monitor():
head = "CommandLine, Time, Executable, Parent PID, PID, User, Privileges"
log2file(head)
c = wmi.WMI()
process_monitor = c.Win32_Process.watch_for('creation')
while True:
try:
new_process = process_monitor()
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 = get_process_privileges(pid)
process_log_message = (
f'{cmdline}, {create_date}, {executable},'
f'{parent_pid}, {pid}, {proc_owner}, {privileges}'
)
print(process_log_message)
print()
log2file(process_log_message)
except Exception:
pass
def get_process_privileges(pid):
try:
hproc = win32api.OpenProcess(win32con.PROCESS_QUERY_INFORMATION, False, pid)
htok = win32security.OpenProcessToken(hproc, win32con.TOKEN_QUERY)
privs = win32security.GetTokenInformation(htok, win32security.TokenPrivileges)
privileges = ''
for priv_id, flags in privs:
if flags == (win32security.SE_PRIVILEGE_ENABLED | win32security.SE_PRIVILEGE_ENABLED_BY_DEFAULT):
privileges += f'{win32security.LookupPrivilegeName(None, priv_id)} |'
except Exception:
privileges = 'N/A'
return privileges
if __name__ == "__main__":
monitor()
测试
- 运行脚本一段时间后,监控到系统进程cscript的创建,具备高权限,并且依赖一个普通的vbs脚本
文件监控程序
功能
- 问题:某些高权限进程会将依赖的脚本文件放到临时目录,将命令写入文件执行,最后再删除,我们必须抢在删除前,修改脚本文件的内容
- 解决:通过win32 api
ReadDirectoryChangeW
,监控某个目录下文件的变化,一旦发现目标文件被创建,则立马将恶意代码注入到目标文件中,使得其被执行