证书固定 防止软件被抓包的方式及代码思路

VB.NET · 8 天前 · 127 人浏览
证书固定 防止软件被抓包的方式及代码思路

方式一:采用python的certifi提供的根证书合集进行校验。
此方式校验宽松,基本所有的https均支持打开。

所以现在用.NET 也来实现的这样的一个功能了,共计三种方式。
1、极为宽松的请求策略。所有的HTTPS均可在软件内请求成功。
2、极为严格的请求策略,只允许一个或多个的域名的叶子证书哈希在软件内,才允许请求成功。
3、中等请求策略,仅允许一个或多个的域名根证书哈希在软件内,才允许请求成功(避免证书续签导致频繁维护)。

第二三种都是属于证书固定,用于防止抓包有较强的效果,但需维护。

以下是实现的具体代码段:

Imports System.IO
Imports System.Net
Imports System.Security.Cryptography.X509Certificates
Imports System.Text
Imports System.Text.RegularExpressions

Public Class Form1
    Private Shared trustedCAs As New List(Of X509Certificate2)

    Private Shared Function ReadPemBundleFromResource() As String
        Dim pemBytes As Byte() = My.Resources.Resource1.TEMP
        Return Encoding.ASCII.GetString(pemBytes)
    End Function

    Private Shared Function ParseCertificatesFromPem(pem As String) As List(Of X509Certificate2)
        Dim list As New List(Of X509Certificate2)
        Dim rx = New Regex("-----BEGIN CERTIFICATE-----(.*?)-----END CERTIFICATE-----",
                           RegexOptions.Singleline Or RegexOptions.CultureInvariant)
        For Each m As Match In rx.Matches(pem)
            Dim base64 As String = m.Groups(1).Value.Replace(vbCr, "").Replace(vbLf, "").Trim()
            Dim raw As Byte() = Convert.FromBase64String(base64)
            list.Add(New X509Certificate2(raw))
        Next
        Return list
    End Function

    ' 初始化 CA
    Public Shared Sub InitCA()
        Dim pem As String = ReadPemBundleFromResource()
        trustedCAs = ParseCertificatesFromPem(pem)

        If trustedCAs.Count = 0 Then
            Throw New InvalidOperationException("未从资源解析到任何 CA 证书。")
        End If

        ' 设置全局验证回调(也可改为 HttpClient 的实例级回调)
        ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12
        ServicePointManager.ServerCertificateValidationCallback =
    Function(sender, cert, chain, sslErrors)
        Try
            If sslErrors <> Net.Security.SslPolicyErrors.None Then
                Return False
            End If

            For Each element In chain.ChainElements
                For Each ca In trustedCAs
                    If String.Equals(element.Certificate.Thumbprint, ca.Thumbprint,
                                     StringComparison.OrdinalIgnoreCase) Then
                        ' 输出匹配的证书信息
                        MessageBox.Show($"匹配证书: {element.Certificate.Subject}{vbCrLf}指纹: {element.Certificate.Thumbprint}",
                                        "匹配成功", MessageBoxButtons.OK, MessageBoxIcon.Information)
                        Return True
                    End If
                Next
            Next
            Return False
        Catch ex As Exception
            Return False
        End Try
    End Function
    End Sub

    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        InitCA()
    End Sub

    Private Async Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        Await Task.Run(Async Function()
                           Await DEMO()
                       End Function)
    End Sub
    Public Async Function DEMO() As Task(Of String)
        ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12
        Dim url As String = $"https://www.jianshu.com/p/a8ddf16fabb2"
        Try
            Dim request As HttpWebRequest = CType(WebRequest.Create(url), HttpWebRequest)
            request.Method = "GET"
            request.Timeout = 10000
            request.KeepAlive = True
            request.Accept = "application/json, text/plain, */*"
            request.UserAgent = "Mozilla/5.0"
            request.Referer = url

            Using response As HttpWebResponse = CType(request.GetResponse(), HttpWebResponse)
                Using reader As New StreamReader(response.GetResponseStream(), Encoding.UTF8)
                    Dim result As String = reader.ReadToEnd()
                    MsgBox(result)
                End Using
            End Using
        Catch ex As Exception
            If ex.Message = "基础连接已经关闭: 未能为 SSL/TLS 安全通道建立信任关系。" Then
                MessageBox.Show($"NOT", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error)
            Else
                MessageBox.Show($"请求异常:{ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error)
            End If
        End Try
        Return ""
    End Function
End Class

注意,我的cacert.pem存放到了资源文件中,并命名为TEMP。

这个cacert.pem文件,则需要安装python环境,使用pip install certifi,通过下面的代码来获取。

import certifi
import os
import shutil

path = certifi.where()
script_dir = os.path.dirname(os.path.abspath(__file__))
target_path = os.path.join(script_dir, "TEMP")
shutil.copy(path, target_path)

print(f"证书已复制到: {target_path}")
input("按回车键退出...")

方式二:采用单域名或多域名进行校验
此方式计算远程站点的证书Leaf的值,进行校验。校验不通过,则请求拒绝。
优点:域名针对性极强。
缺点:此方式校验的是叶子证书的leaf值,校验较为风控,如果证书续签,您需要手动需要进行维护软件。
或者将获取TEMP文件的的方式,改为远程获取。

首先通过python代码获取输入域名并将叶子证书哈希,并输出为TEMP文件。

import argparse, base64, hashlib, socket, ssl, sys
from pathlib import Path
from cryptography import x509
from cryptography.hazmat.primitives.serialization import Encoding, PublicFormat

def vb_compat_pubkey_bytes(cert_der: bytes) -> bytes:
    cert = x509.load_der_x509_certificate(cert_der)
    pub = cert.public_key()
    from cryptography.hazmat.primitives.asymmetric import rsa, ec, ed25519, ed448, dsa
    if isinstance(pub, rsa.RSAPublicKey):
        return pub.public_bytes(Encoding.DER, PublicFormat.PKCS1)
    if isinstance(pub, ec.EllipticCurvePublicKey):
        return pub.public_bytes(Encoding.X962, PublicFormat.UncompressedPoint)
    if isinstance(pub, ed25519.Ed25519PublicKey) or isinstance(pub, ed448.Ed448PublicKey):
        return pub.public_bytes(Encoding.Raw, PublicFormat.RawPublicKey)
    if isinstance(pub, dsa.DSAPublicKey):
        spki = pub.public_bytes(Encoding.DER, PublicFormat.SubjectPublicKeyInfo)
        i = spki.rfind(b'\x03')
        length = spki[i+1]
        unused_bits = spki[i+2]
        return spki[i+3:i+2+length]
    return pub.public_bytes(Encoding.DER, PublicFormat.SubjectPublicKeyInfo)

def get_leaf_der(host: str, port: int = 443) -> bytes:
    ctx = ssl.create_default_context()
    with socket.create_connection((host, port), timeout=5.0) as sock:
        with ctx.wrap_socket(sock, server_hostname=host) as ssock:
            return ssock.getpeercert(True)

def calc_pin(host: str, port: int) -> str:
    der = get_leaf_der(host, port)
    raw = vb_compat_pubkey_bytes(der)
    return base64.b64encode(hashlib.sha256(raw).digest()).decode()

if __name__ == "__main__":
    ap = argparse.ArgumentParser(description="计算多个域名的 pin,仅输出 pin 值,一行一个。")
    ap.add_argument("hosts", help="多个域名,英文逗号分隔,如: example.com,foo.bar")
    ap.add_argument("-p", "--port", type=int, default=443, help="端口(对所有域名生效),默认 443")
    args = ap.parse_args()

    hosts = [h.strip() for h in args.hosts.split(",") if h.strip()]

    pins = []
    for host in hosts:
        try:
            pin = calc_pin(host, args.port)
            pins.append(pin)
        except Exception as e:
            # 错误信息仅写到 stderr,不影响 stdout 的纯 pin 输出和 TEMP 文件内容
            sys.stderr.write(f"[ERROR] {host}: {e}\n")

    # 标准输出:只打印 pin,每行一个
    for pin in pins:
        print(pin)

    # 写入同目录 TEMP(仅 pin,每行一个;覆盖写入)
    temp_path = Path(__file__).resolve().parent / "TEMP"
    temp_path.write_text("\n".join(pins) + ("\n" if pins else ""), encoding="utf-8")

将哈希文件保存到资源文件中,并内存读取。

Imports System.IO
Imports System.Net
Imports System.Net.Security
Imports System.Security.Cryptography
Imports System.Security.Cryptography.X509Certificates
Imports System.Text

Public Class Form1
    ' 从资源读取 pin 列表(每行一个 Base64 的哈希)
    Private Shared Function ReadPinsFromResource() As HashSet(Of String)
        Dim txt As String = Encoding.ASCII.GetString(My.Resources.Resource1.TEMP) ' TEMP:文本文件,非PEM
        Dim setPins As New HashSet(Of String)(StringComparer.Ordinal)
        For Each line In txt.Split({ControlChars.Cr, ControlChars.Lf}, StringSplitOptions.RemoveEmptyEntries)
            Dim pin = line.Trim()
            If pin.Length > 0 Then setPins.Add(pin)
        Next
        Return setPins
    End Function

    Private Shared AllowedPins As HashSet(Of String)

    ' 零依赖版:仅对“公钥位串”做 SHA-256(不是严格SPKI,但兼容老框架、足够实用)
    Private Shared Function SpkOnlySha256B64(cert As X509Certificate2) As String
        Using sha = SHA256.Create()
            Dim spk As Byte() = cert.PublicKey.EncodedKeyValue.RawData
            Return Convert.ToBase64String(sha.ComputeHash(spk))
        End Using
    End Function
   
    Private Shared Function ValidatePin(sender As Object,
                                        certificate As X509Certificate,
                                        chain As X509Chain,
                                        sslErrors As SslPolicyErrors) As Boolean
        Try
            If sslErrors <> SslPolicyErrors.None OrElse certificate Is Nothing Then
                Return False
            End If

            Dim leaf As New X509Certificate2(certificate)

            ' 1) 先校验 leaf
            Dim leafPin = SpkOnlySha256B64(leaf)
            If AllowedPins.Contains(leafPin) Then
                Return True
            End If

            ' 2) 再校验中间证书
            If chain IsNot Nothing AndAlso chain.ChainElements IsNot Nothing Then
                For i = 1 To chain.ChainElements.Count - 1 ' 跳过 0:leaf
                    Dim inter = chain.ChainElements(i).Certificate
                    Dim interPin = SpkOnlySha256B64(inter)
                    If AllowedPins.Contains(interPin) Then
                        Return True
                    End If
                Next
            End If

            ' 未命中任何 pin
            Return False
        Catch
            Return False
        End Try
    End Function

    ' 初始化:加载 pins 并设置全局验证回调
    Public Shared Sub InitCA()
        AllowedPins = ReadPinsFromResource()
        If AllowedPins Is Nothing OrElse AllowedPins.Count = 0 Then
            Throw New InvalidOperationException("资源中未读取到任何 pins。请在 Resource1.TEMP 中按行填写 Base64 pin。")
        End If

        ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12
        ServicePointManager.ServerCertificateValidationCallback = AddressOf ValidatePin
    End Sub

    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        InitCA()
    End Sub

    Private Async Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        Await Task.Run(Async Function()
                           Await DEMO()
                       End Function)
    End Sub

    Public Async Function DEMO() As Threading.Tasks.Task(Of String)
        ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12
        Dim url As String = "https://xxx.cn/test.php"
        Try
            Dim request As HttpWebRequest = CType(WebRequest.Create(url), HttpWebRequest)
            request.Method = "GET"
            request.Timeout = 10000
            request.KeepAlive = True
            request.Accept = "application/json, text/plain, */*"
            request.UserAgent = "Mozilla/5.0"
            request.Referer = url

            Using response As HttpWebResponse = CType(request.GetResponse(), HttpWebResponse)
                Using reader As New StreamReader(response.GetResponseStream(), Encoding.UTF8)
                    Dim result As String = reader.ReadToEnd()
                    ' TODO: 使用 result
                End Using
            End Using
            MessageBox.Show("请求成功", "OK", MessageBoxButtons.OK, MessageBoxIcon.Information)
        Catch ex As Exception
            If ex.Message.Contains("未能为 SSL/TLS 安全通道建立信任关系") Then
                MessageBox.Show("证书校验失败(可能被拦截或证书更换)", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error)
            Else
                MessageBox.Show("请求异常:" & ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error)
            End If
        End Try
        Return ""
    End Function
End Class

方式三:采用请求域名的根证书进行校验
这种也是我当前在用的一种方式。
根证书一般是不需要进行维护。域名续签也不会导致失效,比第一种方式严格(仅允许请求域名)但又比第二种宽松(同根证书下的站点都可以请求)

控制台程序(用以获取根证书的哈希):

Imports System.Net
Imports System.Net.Security
Imports System.Security.Cryptography
Imports System.Security.Cryptography.X509Certificates
Imports System.Text
Imports System.IO

Module Module1
    Sub Main()
        Console.OutputEncoding = Encoding.UTF8
        Console.InputEncoding = Encoding.UTF8

        Console.WriteLine("请输入 HTTPS 域名,多个用英文逗号分隔(例如:https://a.com, b.com):")
        Dim input As String = Console.ReadLine().Trim()

        If String.IsNullOrWhiteSpace(input) Then
            Console.WriteLine("未输入任何域名,程序结束。")
            Return
        End If

        Dim domains = input.Split({","c}, StringSplitOptions.RemoveEmptyEntries) _
                           .Select(Function(s) s.Trim()) _
                           .Where(Function(s) Not String.IsNullOrWhiteSpace(s)) _
                           .ToList()

        If domains.Count = 0 Then
            Console.WriteLine("没有有效的域名输入。")
            Return
        End If

        ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12

        Dim sb As New StringBuilder()

        For Each domain In domains
            Dim url As String = domain
            If Not url.StartsWith("https://", StringComparison.OrdinalIgnoreCase) Then
                url = "https://" & url
            End If

            Console.WriteLine(vbCrLf & "处理: " & url)
            Try
                Dim leaf As X509Certificate2 = GetServerCertificate(url)
                If leaf Is Nothing Then
                    Console.WriteLine("⚠️ 无法获取服务器证书。")
                    Continue For
                End If

                Dim anchor As X509Certificate2 = GetTrustAnchor(leaf)
                If anchor Is Nothing Then
                    Console.WriteLine("⚠️ 无法构建证书链或未找到根证书。")
                    Continue For
                End If

                Dim pin As String = SpkOnlySha256B64(anchor)

                Console.WriteLine("根证书: " & anchor.Subject)
                Console.WriteLine("颁发者: " & anchor.Issuer)
                Console.WriteLine("✅ Root Pin: " & pin)

                sb.AppendLine(pin)
            Catch ex As Exception
                Console.WriteLine("❌ 错误:" & ex.Message)
            End Try
        Next

        ' 写入输出文件(只有 pin)
        Dim outputPath As String = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "root_pins.txt")
        File.WriteAllText(outputPath, sb.ToString().Trim(), Encoding.UTF8)

        Console.WriteLine(vbCrLf & "✅ 已保存纯 pin 到文件: " & outputPath)
        Console.WriteLine("按任意键退出...")
        Console.ReadKey()
    End Sub

    Function SpkOnlySha256B64(cert As X509Certificate2) As String
        Using sha256 As SHA256 = SHA256.Create()
            Dim spk As Byte() = cert.PublicKey.EncodedKeyValue.RawData
            Return Convert.ToBase64String(sha256.ComputeHash(spk))
        End Using
    End Function

    ' 构建证书链并返回信任锚(最后一个元素,通常是系统信任库中的根证书)。失败返回 Nothing。
    Function GetTrustAnchor(leaf As X509Certificate2) As X509Certificate2
        Dim ch As New X509Chain()
        ch.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck      ' 需要时可改为 Online
        ch.ChainPolicy.RevocationFlag = X509RevocationFlag.ExcludeRoot
        ch.ChainPolicy.VerificationFlags = X509VerificationFlags.NoFlag
        ch.ChainPolicy.VerificationTime = DateTime.UtcNow

        If Not ch.Build(leaf) OrElse ch.ChainElements Is Nothing OrElse ch.ChainElements.Count = 0 Then
            Return Nothing
        End If

        Return ch.ChainElements(ch.ChainElements.Count - 1).Certificate
    End Function

    ' 发起一次 TLS 握手以获取服务器返回的叶子证书
    Function GetServerCertificate(url As String) As X509Certificate2
        Dim cert As X509Certificate2 = Nothing

        Dim oldHandler As RemoteCertificateValidationCallback = ServicePointManager.ServerCertificateValidationCallback

        ' 暂时接受任何证书,以便拿到服务器发来的叶子证书
        ServicePointManager.ServerCertificateValidationCallback =
            Function(sender, certificate, chain, sslPolicyErrors)
                If certificate IsNot Nothing Then
                    cert = New X509Certificate2(certificate)
                End If
                Return True
            End Function

        Try
            Try
                Dim reqHead As HttpWebRequest = CType(WebRequest.Create(url), HttpWebRequest)
                reqHead.Method = "HEAD"
                reqHead.Timeout = 5000
                Using resp As HttpWebResponse = CType(reqHead.GetResponse(), HttpWebResponse)
                    ' 仅用于握手
                End Using
            Catch
                Dim reqGet As HttpWebRequest = CType(WebRequest.Create(url), HttpWebRequest)
                reqGet.Method = "GET"
                reqGet.Timeout = 5000
                reqGet.UserAgent = "Mozilla/5.0"
                reqGet.Accept = "*/*"
                reqGet.ReadWriteTimeout = 5000
                ' 读取最少量数据即可触发握手
                Using resp As HttpWebResponse = CType(reqGet.GetResponse(), HttpWebResponse)
                    Using s As Stream = resp.GetResponseStream()
                        Dim buffer(0) As Byte
                        s.ReadTimeout = 2000
                        ' 尝试读取 1 字节,不关心结果
                        s.Read(buffer, 0, 1)
                    End Using
                End Using
            End Try
        Finally
            ServicePointManager.ServerCertificateValidationCallback = oldHandler
        End Try

        Return cert
    End Function
End Module

输出的哈希,放至远程服务器,得到链接,打开软件读取哈希,并根据远程哈希值,进行校验。
注意,远程的地址内容,建议加密一下,在软件读取时再进行解密,不然还是能拦截到请求的,并进行伪造请求内容。

Imports System.IO
Imports System.Net
Imports System.Net.Http
Imports System.Net.Security
Imports System.Security.Cryptography
Imports System.Security.Cryptography.X509Certificates
Imports System.Text
Imports System.Threading.Tasks

Public Class Form1
    ' 远程 pin 列表地址(每行一个 Base64 的 SHA-256 值)
    Private Const PinsUrl As String = "https://test.com/test.txt" '此域名为根证书的公钥哈希,一行一个。
    Private Shared AllowedPins As HashSet(Of String)

    ' 仅对“公钥位串”做 SHA-256(不是严格 SPKI,但兼容老框架)
    Private Shared Function SpkOnlySha256B64(cert As X509Certificate2) As String
        Using sha = SHA256.Create()
            Dim spk As Byte() = cert.PublicKey.EncodedKeyValue.RawData
            Return Convert.ToBase64String(sha.ComputeHash(spk))
        End Using
    End Function

    ' 从远程下载 pin 列表(此阶段未安装 pin 回调 → 不做 pin 校验)
    Private Shared Async Function ReadPinsFromRemoteAsync() As Task(Of HashSet(Of String))
        ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12

        ' 使用默认处理程序即可:只做系统层面的 TLS 校验,不做 pin
        Dim handler As New HttpClientHandler() ' .NET Framework 下,未设置自定义回调时不触发 pin
        Using client As New HttpClient(handler)
            client.Timeout = TimeSpan.FromSeconds(10)
            Dim txt As String = Await client.GetStringAsync(PinsUrl).ConfigureAwait(False)

            Dim setPins As New HashSet(Of String)(StringComparer.Ordinal)
            For Each line In txt.Split({ControlChars.Cr, ControlChars.Lf}, StringSplitOptions.RemoveEmptyEntries)
                Dim pin = line.Trim()
                If pin.Length > 0 Then setPins.Add(pin)
            Next
            Return setPins
        End Using
    End Function

    ' 构建证书链并返回信任锚(最后一个元素,通常是系统信任库中的根证书)。失败返回 Nothing。
    Private Shared Function GetTrustAnchor(leaf As X509Certificate2) As X509Certificate2
        Dim ch As New X509Chain()
        ch.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck      ' 生产可改为 Online
        ch.ChainPolicy.RevocationFlag = X509RevocationFlag.ExcludeRoot
        ch.ChainPolicy.VerificationFlags = X509VerificationFlags.NoFlag
        ch.ChainPolicy.VerificationTime = DateTime.UtcNow

        If Not ch.Build(leaf) OrElse ch.ChainElements Is Nothing OrElse ch.ChainElements.Count = 0 Then
            Return Nothing
        End If

        ' 最后一个就是信任锚(根)
        Return ch.ChainElements(ch.ChainElements.Count - 1).Certificate
    End Function

    ' 证书 pin 校验回调 —— 只校验“根”的公钥哈希
    Private Shared Function ValidatePin(sender As Object,
                                        certificate As X509Certificate,
                                        chain As X509Chain,
                                        sslErrors As SslPolicyErrors) As Boolean
        Try
            If sslErrors <> SslPolicyErrors.None OrElse certificate Is Nothing Then
                Return False
            End If

            If AllowedPins Is Nothing OrElse AllowedPins.Count = 0 Then
                Return False
            End If

            Dim leaf As New X509Certificate2(certificate)

            Dim anchor As X509Certificate2 = GetTrustAnchor(leaf)
            If anchor Is Nothing Then
                Return False
            End If

            Dim rootPin As String = SpkOnlySha256B64(anchor)

            Return AllowedPins.Contains(rootPin)
        Catch
            Return False
        End Try
    End Function

    Public Shared Async Function InitCAAsync() As Task
        ' 先下载 pin(此时尚未设置 ServerCertificateValidationCallback)
        AllowedPins = Await ReadPinsFromRemoteAsync().ConfigureAwait(False)

        If AllowedPins Is Nothing OrElse AllowedPins.Count = 0 Then
            Throw New InvalidOperationException("未从远程获取到任何 pins。请检查 " & PinsUrl)
        End If

        ' 再安装全局回调:此后所有 TLS 请求才开始做 pin 校验
        ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12
        ServicePointManager.ServerCertificateValidationCallback = AddressOf ValidatePin
    End Function

    Private Async Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        Try
            Me.Text = "获取配置中.."
            Await Task.Run(Async Function()
                               Await InitCAAsync()
                           End Function)

            Me.Text = "配置获取完成 - 防抓包已开启"
        Catch ex As Exception
            MessageBox.Show("初始化失败:" & ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error)
            End
        End Try
    End Sub

    Private Async Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        Await Task.Run(Async Function()
                           Await DEMO()
                       End Function)
    End Sub

    Public Async Function DEMO() As Task(Of String)
        ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12
        Dim url As String = "https://xxx.cn/test.php"
        Try
            Dim request As HttpWebRequest = CType(WebRequest.Create(url), HttpWebRequest)
            request.Method = "GET"
            request.Timeout = 10000
            request.KeepAlive = True
            request.Accept = "application/json, text/plain, */*"
            request.UserAgent = "Mozilla/5.0"
            request.Referer = url

            Using response As HttpWebResponse = CType(request.GetResponse(), HttpWebResponse)
                Using reader As New StreamReader(response.GetResponseStream(), Encoding.UTF8)
                    Dim result As String = reader.ReadToEnd()
                    MessageBox.Show(result, "OK", MessageBoxButtons.OK, MessageBoxIcon.Information)
                End Using
            End Using
        Catch ex As Exception
            If ex.Message.Contains("未能为 SSL/TLS 安全通道建立信任关系") Then
                MessageBox.Show("This request has been blocked.", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error)
            Else
                MessageBox.Show("请求异常:" & ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error)
            End If
        End Try
        Return ""
    End Function
End Class

使用方式三的示例:
可测下防抓包强度,已加DNG壳,但我获取哈希时并未进行加密,是可以通过抓包工具,首先替换请求中的哈希,应该是可以突破的,在具体生产中,是必须要进行加密的。但如果进行突破,就算没有对远程地址进行加密,也并不是点几下鼠标就可以搞定的事情。

12.png
下载地址:https://400.lanzout.com/igVQR376owxg