Proxifier强制代{过}{滤}理HTTP绕过身份检测

查看 84|回复 13
作者:alexsuntop   
题主非逆向专业,如有不足请多多海涵。这是题主第一次发帖,这里描述的内容可能过于抽象或不详细,如果有其他问题我将继续更新以供学习交流。

似乎所有代==理,都被加了 {过}{滤},第一次用 52,额

最近发现一个付费软件使用 HTTP 验证是否购买,所以想绕过直接使用。考虑到软件方商业权益和本帖合法性,暂时不提供相关软件的任何信息,本帖只提供思路。

这里提醒一下,如果你没有已经购买过的样本来学习,那这一点还是很难实现的,还是老老实实脱壳破解吧。题主有幸得到一份已经购买过朋友的样本,所以学到了验证方法。

首先题主通过 Fiddler 拦截请求,实现了上述过程,把有效的返回替换了原有返回内容,成功实现了注册。然后在虚拟机中试验成功了。
软件使用了 HTTP 没用 HTTPS,直接访问 IP 地址的。现在的思路是使用 Proxifier 强制软件走代{过}{滤}理,然后自己编写一个 HTTP 服务作为代{过}{滤}理服务器。Proxifier 默认不允许 HTTP 代{过}{滤}理,需要手动开启一下。

本来想软件如果通过域名访问,直接修改 hosts 把域名重定向到本地就好了,发现只访问 IP 还挺麻烦,目前没想到能不使用 Proxifier 的方法,如有方法还请评论区建议。
题主主修人工智能,因此擅长 Python,通过 Python aiohttp 框架编写一个 HTTP 服务器,并代{过}{滤}理一个 IP 下的服务:
import asyncio
import re
import socket
from datetime import datetime, timedelta
from multiprocessing import Queue
from aiohttp import ClientSession
from aiohttp.web import Application, Request, Response, RouteTableDef, run_app
from src.config import LOCK_VERSION, TARGET_HOST, TARGET_PORT, TEMPLATE
routes = RouteTableDef()
def is_port_available(host: str, port: int) -> bool:
    """检查端口是否可用"""
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    result = sock.connect_ex((host, port))
    sock.close()
    return result != 0
async def _make_proxy(request: Request) -> Response:
    """返回代{过}{滤}理数据"""
    async with ClientSession() as session:
        async with session.request(
            method=request.method,
            url=f"http://{TARGET_HOST}:{TARGET_PORT}{request.path}",
            headers=request.headers,
            params=request.query,
            data=await request.read() if request.can_read_body else None,
        ) as response:
            headers = {
                "Accept": response.headers.get("Accept", ""),
                "Host": response.headers.get("Host", ""),
                "Content-type": response.headers.get("Content-type", ""),
                "Set-Cookie": response.headers.get("Set-Cookie", ""),
                "Expires": response.headers.get("Expires", ""),
                "Referer": response.headers.get("Referer", ""),
                "Location": response.headers.get("Location", ""),
                "User-Agent": response.headers.get("User-Agent", ""),
                "Cookie": response.headers.get("Cookie", ""),
            }
            headers.pop("Transfer-Encoding", None)
            return Response(
                body=await response.read(),
                headers=headers,
                status=response.status,
            )
软件通过字符串匹配获取软件的余剩使用日期(不得不说太 low 了),直接注册到两年后。
这就是一个基本的 HTTP 代{过}{滤}理服务,下面是代{过}{滤}理 GET 请求:
@routes.get("/{tail:.*}")
async def proxy_get(request: Request):
    """代{过}{滤}理所有 GET 请求"""
    queue: Queue = request.app["queue"]
    current_date = datetime.now().strftime("%Y-%m-%d")
    code = request.query.get("s_code", "")
    # 注册拦截器
    if "/reg.php":
        end_date = (datetime.now() + timedelta(days=730)).strftime("%Y-%m-%d")
        queue.put(f"获取到机器码:{code},正在注册到 {end_date}。")
        return Response(
            text=TEMPLATE.format(
                code=code,
                current_date=current_date,
                end_date=end_date,
            ),
            headers={
                "Content-type": "text/html; charset=UTF-8",
            },
        )
    is_locked = request.app.get("is_locked", False)
    # 检查是否锁版本
    if "/update.php" in request.path and is_locked:
        queue.put(f"检测到版本请求,已锁定版本")
        return Response(
            text=LOCK_VERSION.format(
                current_date=current_date,
            ),
            headers={
                "Content-type": "text/html; charset=UTF-8",
            },
        )
    return await _make_proxy(request)
解释一下:
  • queue:进程队列
  • LOCK_VERSION:是否锁定版本,如果有需求可以自己设计
  • TARGET_HOST:目标主机 IP
  • TARGET_PORT:代{过}{滤}理目标端口
  • TEMPLATE:返回的模板代码,自己根据需要写

    锁定版本是防止软件强制更新,我已经抓到以前的响应模板,这样如果需要锁定版本可以直接发送之前的更新请求的响应。
    这里进程队列用于和其他进程通信,这里我使用 Python 标准库 TK 来设计 UI。可以通过 UI 查看日志信息。
    下面是运行服务的代码:
    @routes.post("/{tail:.*}")
    async def proxy_post(request: Request):
        """代{过}{滤}理所有 POST 请求"""
        return await _make_proxy(request)
    def run_simple_server(queue: Queue, host: str, port: int):
        """运行服务器"""
        app = Application()
        app["queue"] = queue
        app.add_routes(routes)
        if not is_port_available(host, port):
            queue.put(f"端口 {port} 被占用!请勿重复打开程序,现在请关闭全部程序后重试。")
            return
        try:
            queue.put(f"注册机启动成功!")
            queue.put({"msg": "ready"})
            run_app(app, host=host, port=port)
        except RuntimeError:
            pass
    if __name__ == "__main__":
        run_simple_server(Queue(), "127.0.0.1", 8899)
    我这里还使用多进程以便能通过进程通信:
    import multiprocessing as mp
    from src.server import run_simple_server
    from src.ui import simple_tkinker_ui
    HOST = "127.0.0.1"
    PORT = 8899
    if __name__ == "__main__":
        mp.freeze_support()
        queue = mp.Queue()
        p1 = mp.Process(target=run_simple_server, args=(queue, HOST, PORT))
        p1.start()
        p2 = mp.Process(target=simple_tkinker_ui, args=(queue, HOST, PORT))
        p2.start()
    如果你觉得你不需要 UI,可以删除对应部分运行,直接打印日志。
    UI 的代码太长,没有放出来。其实也无关紧要,以上代码用来学习测试即可。
    这里使用 Nuitka 打包代码:
    @echo off
    python -m nuitka --standalone --onefile ^
        --mingw64 --show-progress --disable-console ^
        --plugin-enable=tk-inter --output-dir=dist ^
        --assume-yes-for-downloads main.py
    这样每次使用软件之前启动一下脚本和 Proxifier,软件就以为自己已经注册过了。
    不知道有没有更简单的,在 Windows 上实现 HTTP 拦截的方法。因为请求是 IP 地址没有加密,理论上可以在网关上拦截然后不再需要注册机和 Proxifier,但是有点复杂,Linux 似乎有工具直接支持拦截 HTTP 包。
    先写到这,如果有不详细的地址再更新。

    软件, 版本

  • ghostwindows   

    fidller有一个插件可以直接重定向到本地文件,叫stave
    moonlune   

    此类似类方法很久以前用过,但是当时使用的是Proxomitron。原理是,某个软件每次启动都会http联网发送一个验证,如果是符合的验证码,那么会返回某段注册成功信息。然后只要把返回的某段信息无论是什么,都给修改为返回注册成功信息,就可以了。
    wfghim   

    pc端,有个收费软件,是验证mac地址的,每个mac地址可以试用3天,每次打开软件,都用mac地址请求服务器,服务器返回可以试用的天数,我用Fiddler Script 篡改了响应的报文,达成了白嫖
    pentest686   


    cyhcuichao 发表于 2024-3-20 23:40
    APP有代{过}{滤}理检测 只要打开就不能截包有什么办法吗

    1、使用基于VPN模式的Postern
    vproxid、rproxid、
    https://github.com/postern-overwal/postern-stuff
    2、使用基于iptables的ProxyDroid
    https://github.com/cxf-boluo/mag ... /org.proxydroid.apk
    夏驰   

    感谢分享,但是新手还是不会操作
    lambchasr   

    mark,收藏备用
    听说哥   

    虽然不知道怎么用,感谢分享
    pentest686   

    mitmproxy应该可以,mitm监听80端口,再通过host将域名定位到本机。只启动mitmproxy就可以,不是开发,不擅长编程,仅提供思路
    juqkai   

    如果是你自己用,感觉可以去路由器里面找找,看有没有拦截转发的功能,
    您需要登录后才可以回帖 登录 | 立即注册

    返回顶部