[参考]Powershell简单入门

由于诸多样本都使用Powershell执行无文件攻击,加载本文可能会触发您的杀毒软件报告。本文不下载任何文件,不执行任何文件,请放心加载!!

于实战中应用Powershell

Powershell是一个基于.NET(包括.NET Core (Powershell 6.0)、.Net Framework)的基于任务的自动化命令行。简单地说,他比cmd和VBSript相比而言提供了更多功能,并且可以支持.NET代码,这意味着可以在脚本解释器中直接嵌入大量复杂代码。

Powershell作为无文件攻击的一种有效的手段,在诸多APT、商业攻击中被广泛使用。由于其强大的命令执行功能,Powershell的脚本可以做到规避部分AV、EDR等。[1]

作为批处理的一种方式,它提供了一种更加方便的方法来操作计算机中的诸多文件和操作,可以很大程度上自动化很多繁琐的操作。从维护计算机的方向上,我们可以通过编写powershell脚本对诸多任务实施自动化,类似于Python,其语法简单,系统自动支持,因此十分强大。

基于Powershell的真实样本列表(部分)

由于样本的危险性,这里不给出详细的样本获取链接。

  • Kthmimu[2]
  • WannaRun
  • KillMBR[3]
  • 诸多APT
  • Ransomeware[4]

Powershell脚本语言基础

杂项

  1. 注释:#

    # 在此处键入注释
    <#
    这里是块注释
    #>
    
  2. 变量:$

    $var1 = $null	#所有变量的初值都为$null
    ${var-1} = $null	#含有特殊字符,需要使用大括号声明变量
    ${D:\var} = 1	#将变量的值动态的保存到对应的文件内
    [int]$var = 1	#指定变量类型
    [ValidateRange(1,10)][int]$var = 1	#指定变量范围
    
    • 打印变量:

      • 直接输出:$var将直接输出变量内容
      • 通过格式化(见下方): echo ('var = {0}' -f $var)
    • 删除变量:Clear-Variable -Name var或者clv var

    • 查看变量类型:$var.GetType()

    • 作用域:$[<scope-modifier>:]<name> = <value>

自动变量[5]

  1. 常用自动变量

    • $?:上一次执行成功。成功返回True

    • $$:返回上一个指令的最后一个令牌(token)
      $^:返回第一个token

      例如

      echo a b c
      $var_last = $$	# = c
      $var_first = $^	# = echo
      
    • $_:常与Foreach-Object配套使用,代表传入当前循环的token

      别名为$PSItem(token中包含当前对象)

      Foreach-Object也可以用%代替,例如 1,2,3 | %{ write-host $_ }

  2. 系统缺省变量

    • $args:参数

    • $foreach:循环计数器,用于快速确定foreach的循环次数

    • $MyInvocation.MyCommand.Path:当前脚本的执行位置(包括文件名)

      $MyInvocation是非常常用的变量,因此善用可以加快自动化的速度

字符串

全文本字符串

使用单引号'包裹,在这个单引号内部的所有内容都不会被转义。

$var = 1
echo 'var = $var'	#输出var = $var

软字符串

使用双引号"包裹,这个双引号内部可以包含变量,自动格式化

$var = 1
echo "var = $var"	#输出var = 1

Here-String

用于

  • 多行
  • 包括单双引号的字符串
  • 帮助文本
@'
这里面的变量不会被转义
'@

$var = ”变量“
@"
这里面的$var会被转义
"@

杂项

  • 拼接:$s1 + $s2

    也可以使用运算符完成上述操作$s1,$s2 -join
    或者利用.NET:[System.String]::Concat($s1,$s2)

  • 子串:$s1.SubString(3,5)

  • 字符串格式化:'{0} -f $var',注意这里格式化不需要考虑上述的单双引号规则

  • 替换:$s1.Replace('a','b')

数组

和变量声明相同

$k = @()		#初始化空数组
$k = 1,2,3,4,5	#初始化五元数组
$k = ($k[0..3])	#删掉最后一个值
$k += 5			#增加一个项目
$k[-1]			#显示最后一个项目
$k[2..4]		#访问第三个到第五个项目
$k[-4..-1]		#从后往前显示这些项目

数学运算符

  1. +.-,*,/,%常识无区别

  2. 比较

    -eq		#	==
    -ne		#	!=
    -gt		#	>
    -ge		#	>=
    -lt		#	<
    -le		#	<=
    
  3. 输出到

    >	#	将内容输出到文件
    >>	#	将内容追加到文件
    

    输出到是个很复杂的运算符,参见微软文档。[6]

基础语句

If-Else/Do-While/Switch/For/While都和普通编程语言无异

ForEach

Foreach($<item> in $<collection>)  
{  
     Statement-1  
     Statement-2  
     Statement-N  
}

函数

常规函数

function [<scope:>]<name> [([type]$parameter1[,[type]$parameter2])]  
{  
  param([type]$parameter1 [,[type]$parameter2])  
  dynamicparam {<statement list>}  
  begin {<statement list>}  
  process {<statement list>}  
  end {<statement list>}  
}

高级函数

高级函数的区别是,高级函数可以像cmdlets一样调用,亦即

#普通函数
Function(0,1)
#高级函数
Advanced_Func 0 1

其实现比较复杂,使用的不多

function Send-Greeting
{
    [CmdletBinding()]
    Param(
        [Parameter(Mandatory=$true)]
        [string] $Name
    )

    Process
    {
        Write-Host ("Hello " + $Name + "!")
    }
}

参见微软文档[7]

实用Powershell脚本示例

批量修改文件属性


$Path = Split-Path -Parent $MyInvocation.MyCommand.Path
$Files = Get-ChildItem -Path $Path
foreach ($File in $Files)
{
    $Years = 2022
    $Month = Get-Random -Minimum 1 -Maximum 12
    $Day = Get-Random -Minimum 1 -Maximum 30
    
    $Hours = Get-Random -Minimum 0 -Maximum 24
    $Minutes = Get-Random -Minimum 0 -Maximum 60
    $Seconds = Get-Random -Minimum 0 -Maximum 60
    $NewTime = ("$Years-$Month-$Day {0}:{1}:{2}" -f $Hours,$Minutes,$Seconds)
    $File.LastAccessTimeUtc = $NewTime
    $File.LastWriteTimeUtc = $NewTime
    $File.CreationTimeUtc = ("$Years-$Month-$Day {0}:{1}:{2}" -f $Hours,$Minutes,$Seconds)
    if($File.Extension.ToString() -ne '.ps1')
    {
        $NewName = [guid]::NewGuid()
        $File.MoveTo("$NewName.txt")
        [guid]::NewGuid() > "$NewName.txt"
    }
    if((Get-Random -Maximum 100 -Minimum 5 ) -eq 40)
    {
        try {
            $File.Delete()
        }
        catch {
            Write-Host ('Error@delete {0}' -f $File.FullName) -ForegroundColor Red
        }
    }
    $ErrorActionPreference = "Stop"
    try {
        throw 'Expected throable object!'
    }
    catch {
        Write-Host ('Error@delete {0}' -f $Error[0].ErrorDetails) -ForegroundColor Yellow
    }
}

获取本机的CIM管理类

$ErrorActionPreference = "Stop"
function Get-WmiNamespace{
    Param ($Namespace='ROOT')
    Try {
        Get-WmiObject -Namespace $Namespace -Class __NAMESPACE | ForEach-Object{
            ($ns='{0}\{1}' -f $_.__NAMESPACE, $_.Name)
            Get-WmiNamespace -Namespace $ns
        }
    }
    Catch {
        Write-Host ('Error@Namespace: {0} - {1}' -f $Namespace, $Error[0])
    } 
}
$WmiClasses = Get-WmiNamespace | ForEach-Object{
    $Namespace = $_
    Try {
        Get-WmiObject -Namespace $Namespace -List | ForEach-Object{ 
            '{0},{1}' -f $Namespace, $_.Path.ClassName
        }
    }
    Catch {
        Write-Host ('Error@Class: {0} - {1}' -f $Namespace, $Error[0])
    }
} | Sort-Object -Unique
Set-Content -Path 'D:\WmiContents.txt' -Value $WmiClasses

从远端请求文件——powershell爬虫

这个就很简单啦,利用Invoke-RestMethod的方法可以快速从互联网上下载文件

一个实例:使用 PowerShell 爬取妹子图网站 | 存在感消失的地方|ω•`) (akarin.dev)

下面是调用可断点续传的一个简单指令

$save_to = (Split-Path -Parent $MyInvocation.MyCommand.Path) + ('\7z.exe')
Start-BitsTransfer -Source 'https://www.7-zip.org/a/7z2201-x64.exe' -Destination $save_to

添加任务计划程序

$action = New-ScheduledTaskAction -Execute "C:\Windows\System32\cmd.exe" -Argument "-c echo hellworld > D:\hello.txt" 
$trigger = New-ScheduledTaskTrigger -Once -At (Get-Date)
$principal = New-ScheduledTaskPrincipal -UserId "$env:ComputerName\$env:UserName" -RunLevel Highest
$settings = New-ScheduledTaskSettingsSet
$task = New-ScheduledTask -Action $action -Principal $principal -Trigger $trigger -Settings $settings
Register-ScheduledTask T1 -InputObject $task

Invoke-Command/Invoke-Expression

伪装、隐藏所有脚本,广泛用于实战样本中。

下面的指令将会执行字符串内的指令

$cmd = Read-Host 'Please input a command'
Invoke-Expression $cmd

因此可以混淆

(一个假题)

$flag = 'fake_flag'

$binary = 
@'
F0Ol^UJd^UJd`jSe_@?wV0Gm`ENHGCG._iOm_TSNVUOlFA-dHCKt_Di-IS?eaDddIS?e`jSra@>hQUiG_kWsV/C-^T6rIh.2N/6q_TCrW@2NVUOlHNlhOjipWUJdMP?EWUNqN/em_DOGaDSqF@.NVUOlF@OPaT2R^T.iRDC-^>lhaDiqWS6vWUK._ENdMP>t@jWs`jSeV/dlGBWm_DRd^T1dGBWm_DSwHNm4@f>dF@>haDiqWS6vWUK._ENdHw-dGBWm_DRrN0GiVUOm_/2R^T.iIh.m_Dum`/Sg_/2h@k-H^TVlGEOm_TSc`jSwaTu-F@.pa@>/J@hHbtldF@>d^TVlGEOm_TSc`jSwaTu-F@.ka@>0J@hHF@>dFEpHF@>dF@>dF@>hWjueWv>6F@aj_DCkb0GiVTucWjueW0-k@f>dF@>dF@>dF/Sg^D5dGDWpVT`HF@>dFE-HcN::
'@
#binary = 
<#
I3RoaXMgaXMgcmVhbCBzY3JpcHQKJFJ1blRpbWVQYXRoID0gKFNwbGl0LVBhdGggLVBhcmVudCAkTXlJbnZvY2F0aW9uLk15Q29tbWFuZC5QYXRoKQokRmlsZXMgPSBHZXQtQ2hpbGRJdGVtIC1QYXRoICRSdW5UaW1lUGF0aAokdGltZV9yZXN1bHQgPSAwCmZvcmVhY2goJEZpbGUgaW4gJEZpbGVzKQp7CiAgICAkdGltZV9yZXN1bHQgKz0gJEZpbGUuQ3JlYXRpb25UaW1lLk1pbGxpc2Vjb25kCn0KaWYoJHRpbWVfcmVzdWx0IC1sdCA2MCkKewogICAgaWYoJHRpbWVfcmVzdWx0IC1ndCA3MCkKICAgIHsKICAgICAgICAkZmxhZyA9ICdmbGFne3JlYWxfZmxhZ30nCiAgICAgICAgI2VjaG8gJGZsYWcKICAgIH0KfQ==
#>

<#
#this is real script
$RunTimePath = (Split-Path -Parent $MyInvocation.MyCommand.Path)
$Files = Get-ChildItem -Path $RunTimePath
$time_result = 0
foreach($File in $Files)
{
    $time_result += $File.CreationTime.Millisecond
}
if($time_result -lt 60)
{
    if($time_result -gt 70)
    {
        $flag = 'flag{real_flag}'
        #echo $flag
    }
}
#>
#[int]$i =0
#for ($i = 0; $i -lt $binary.Length; $i++) 
#{
#    $c = $binary[$i]
#    [int][char]$c = [int][char]$c - 3
#    $c = [char][int]$c
#    [char] $k = [char]$c
#    Write-Host "$k" -NoNewline
#}

附录


  1. Command and Scripting Interpreter: PowerShell, Sub-technique T1059.001 - Enterprise | MITRE ATT&CK® ↩︎

  2. 活跃的Kthmimu挖矿木马分析 (antiy.cn) ↩︎

  3. MalwareBazaar | Browse malware samples (abuse.ch) ↩︎

  4. '8e2a***a00b' ↩︎

  5. about Automatic Variables - PowerShell | Microsoft Learn ↩︎

  6. about Redirection - PowerShell | Microsoft Learn ↩︎

  7. about Functions Advanced - PowerShell | Microsoft Learn ↩︎

posted @ 2022-11-19 18:49  二氢茉莉酮酸甲酯  阅读(414)  评论(0编辑  收藏  举报