powershell简单入门
前言
powershell是微软出品的一款shell语言工具,它的出现给运维人员提供了一种更高效的系统管理方式。同样,正因为其高效,强大,天然免杀(现在会拦截)等特性也被广泛地用于后渗透中。本文记录了一些在入门powershell中的心得。
本文主要参考了 Powershell攻击指南黑客后渗透之道系列
这个系列的文章中的一些案例
https://www.anquanke.com/post/id/87976
本文的操作环境在windows 10虚拟机和osx 14.6上,powershell版本为5.1.18362.752。
基本的语法
灵活使用Help,获取命令帮助手册,例如Help Process获取名字中带有Process的所有cmdlet和function。
比较重要的就是直接使用-example
来看运行示例来快速学习。正因为这点的存在,个人觉得上手powershell不是特别困难。
或者还可以直接使用Get-Command -Noun 要查找的东西 也能达到一样的效果。
Powershell提供程序,本质上是一个适配器,包括接收一系列存储的数据,然后以一种统一的方式使用他们,值得一提的是powershell就是通过这个机制,可以通过和操作文件系统类似的方式操作环境变量,注册表等系统。
Get-PSProvider 获取提供程序的类型
- Get-PSDrive 获取当前session中的驱动
通过 item等方法操作适配器中的内容
支持使用Get-Item Env:/PATH的方式获取变量名称
Set-ItemProperty -Path . -Name xxx -Value 1来设置 当前目录(也可以是注册表)下xxx的值
- 一条cmdlit中并不是全部的属性都是可以用的 例如可以在文件系统中使用Dir -filter,但是在注册表中就不能,必须使用Dir -include,例如在文件系统中的文件就不能使用set-item来设置值。
powershell array
创建方法
$item=1,2,3,4 1,2,3,4
$tem=1,,2 1,2
$tem=1..3 1,2,3
$array=1,”2017”,([System.Guid]::NewGuid()),(get-date)
@(1..2) 1,2
常见方法
$a.count计数
$a.length 长度
$a[0..2] $a[0] $a[1] $a[2] [-3.-1]也支持这样的反序
这里还有个特殊案例:
有连接 slice的作用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
$a = 0..9
$a[+0..2+4..6+8]
0
1
2
4
5
6
8rank 数组的维度
$null 空对象
clear 清空方法
ForEach
1
2
3
4
$a = @(0 .. 3)
$a.ForEach({ $_ * $_})$a=ipconfig $a[0]第一行输出
数组判断 $test -is [array]
数组追加 $test+=1
hashtable
1
2
3
4
5
6
$hashtable=@{} #创建
$hashtable["name"]=123 #赋值
$hashtable.remove("name") # 删除
Get-Member,select-Object, where-Object(遍历对象) $_当前管道中的对象
Get-Member允许列出成员属性并使用属性名称进行筛选
1
2
Get-Process | Get-Member -Name Hand*select-Object
1
2
3
4
5
6
7
8
9
10
Get-CimInstance -Class Win32_LogicalDisk |
Select-Object -Property Name, @{
label='FreeSpace'
expression={($_.FreeSpace/1GB).ToString('F2')}
}判断符号
需要注意的是 powershell为了不和一些特殊符号冲突,一般不使用>,=这些符号。-eq :等于
-ne :不等于
-gt :大于
-ge :大于等于
-lt :小于
-le :小于等于
-contains :包含
$array -contains something
-notcontains :不包含
!($a): 求反
-and :和
-or :或
-xor :异或
-not :非
ForEach-Object
-Process {} 执行的过程脚本块 -Begin 初始化脚本块 -End 结束
输出 $_.Id 大于 1000的 进程
1
2
3
4
Get-Process| ForEach-Object -Process {if($_.Id -gt 1000){$_
.Name+','+$_.Id}}函数
1
2
3
4
5
6
7
8function test($strings){
$strings
}
function test1{
param($strings)
$strings
}if elseif else 一样的
powershell 管理员模式
Start-Process powershell -Verb runAs 需要过uac
创建对象
powershell最强大的一点是直接调用.net对象,这点非常爽。
new-object 新建对象多线程
一种做法是使用start-job来控制,另外中是采用创建powershell对象,采取线程池的形式控制,具体如何做到的下文会给个例子。
一些练习的脚本
- 端口扫描脚本
- System.Net.Sockets.TcpClient 建立对象来测试端口扫描
- System.Net.NetworkInformation.Ping 来扫描ip
- 多线程扫描
- 采用RunspacePool 限制线程数量
- [powershell]::Create()手动创建脚本 $(Function:function_name)指定function
- BeginInvoke() 启动脚本
- EndInvoke()获得返回结果,扫描结果统一由PortScan变量存储
1 | function PortScan { |
总结
主要踩的坑还是在程序的设计,如何保存端口扫描的结果一开始还是想用全局变量来存储,不过没弄出来。最后采用了返回变量这种方式来实现。以后可以选择分析一下PowerSploit的Invoke-Portscan.ps1来学习一下多线程扫描的实现。