#1
刘邦
· 2026-04-25 07:39:10
stalltrix
来了这里好久了,随便发点东西吧。
这个东西并不复杂,就是基本原理而已,估计大伙都知道。献丑了哈哈哈。
注意,此逆向技术与软件逆向技术,有着本质上的区别。软件逆向是分析出原来的代码逻辑。
而API逆向只是思考如何伪装为原来的客户端/浏览器,来请求服务器。让服务器认为是“自己人”而已
其实两种逆向技术差不多,本质上都是伪装为客户端请求服务器
抛砖引玉一下,先说说网页逆向
如果我们使用浏览器请求,那么打开F12,就能看到浏览器的请求数据。
当我们使用工具请求而不是浏览器请求,如何让网站以为是“自己人”呢?这就需要一系列伪装技术。现在浏览器领域,有很多爬虫技术,我们可以凑合用用。
selenium, undetected_chromedriver, drissionpage 这些现成工具就不介绍了,就当大家已经了解了。关键就在于绕过目标系统的 浏览器完整性检测。
此外,也可以使用BrowserMob Proxy 生成 HAR 文件来获取目标数据格式,
HAR是记录浏览器与服务器交互数据的文件格式,一般是用来性能分析和问题调试的。但是我们可以滥用这个来玩爬虫与逆向。
所谓API逆向,就是把目标网站的api,让软件直接通过v1系列的api使用。而实现这个目标主要分为两部分:1.软件接收/v1/的api请求,2.把请求包装为目标网页的数据格式发给网页。
而回来的路径也相同,1.网页返回数据,软件解析数据,并包装为/v1/的api接口返回给客户端。
既然知道了关键在于伪装为网页的“自己人”请求的模拟,我们首先就要先看看网页上的请求是怎么样的,最简单的方法就是打开F12,访问一下并抓个包看看。
首先我们打开某个chat ai的网页,输入任意聊天内容,让浏览器截获并记录请求

可以看到这里的请求路径,请求格式。以及响应格式。
那么我们就需要模拟我自己人,我们浏览器可以看到这些请求头
```
POST /api/chat HTTP/2
Host: chat.xxxx.xx.con
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:140.0) Gecko/20100101 Firefox/140.0
Accept: text/event-stream
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate, br, zstd
Referer: https:/chat.xxxx.xx.con/
Content-Type: application/json
Content-Length: 4505
Origin: https://chat.xxxx.xx.con
Connection: keep-alive
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: cors
Sec-Fetch-Dest: empty
```
> 注:为了避免敏感举例问题,上面的chat.xxxx.xx.con是打码网址。
为了避免被服务器发现并禁止我们访问,我们就需要模拟上述请求头(当然使用HAR文件是最简单的,但是这里为了让大家看的更清楚。我们手工举例)。
常见chat网址,都有浏览器完整性检查。为了绕过完整性检查,上面说的 undetected_chromedriver, drissionpage就派上用场了。
下面我们以DrissionPage为例
使用ChromiumPage获取页面以及绕过检测,然后以SessionPage模拟api发送请求(后续其实可以不使用SessionPage了,直接让软件使用cookie与header,使用gp-http-client请求比较快)
ChromiumPage就这样用的,设置header与cookie请求
```python
from DrissionPage import ChromiumPage
page = ChromiumPage()
page.set.extra_headers({
'Authorization': 'Bearer xxx',
'X-Test': '123'
})
page.set.user_agent('Mozilla/5.0')
page.set.cookies({
'name': 'sessionid',
'value': 'abc123',
'domain': '.example.com'
})
page.get('https://example.com')
```
后续可以不通过ChromiumPage了,直接SessionPage请求就完事了。不过大多数都是直接使用golang写一个来请求。
SessionPage就这样请求,记得带上相同的cookie、header、user-agent。某些网址IP地址也存在cookie对应,这种要使用相同的代理IP
```
session = SessionPage()
session.set.cookies(cookies)
page.set.extra_headers({
'Authorization': 'Bearer xxx',
'X-Test': '123'
})
page.set.user_agent('Mozilla/5.0')
r = session.post(
'https://example.com/api/chat',
data={'a':1,'b':2}
)
print(r.text)
```
某些网址的参数长期不变,这种甚至都不需要ChromiumPage自动化请求,第一次人工抓包,后续直接请求就行了。
这种难度低多了,基本上不需要像上面的网页逆向接口一样经常更新与换。基本稳定不变的。
```python
from flask import Flask, request, jsonify
import time
import uuid
app = Flask(__name__)
@app.route("/v1/chat/completions", methods=["POST"])
def chat_completions():
data = request.json
messages = data.get("messages", [])
model = data.get("model", "fake-gpt")
user_message = ""
if messages:
user_message = messages[-1].get("content", "")
reply = f"Echo: {user_message}"
response = {
"id": "chatcmpl-" + uuid.uuid4().hex[:24],
"object": "chat.completion",
"created": int(time.time()),
"model": model,
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
"content": reply
},
"finish_reason": "stop"
}
],
"usage": {
"prompt_tokens": 0,
"completion_tokens": 0,
"total_tokens": 0
}
}
return jsonify(response)
if __name__ == "__main__":
app.run(host="0.0.0.0", port=8080)
```
请求localhost:8080,模型选择model = data.get("model", "fake-gpt")这里设置的 就返回数据了。上面的这个例子,返回的回显的数据。实际上应该返回动态从网页那边返回的数据,
好了,差不多就是这样。不过提醒一点,现在的很多网页,都有额外的header或者cookie session做防护。要注意这一点不要漏了。
此外,逆向agent的方法与逆向网页差不多,就是“4.网页模拟入门”这个方法改一下,后续都不要改的,模拟网页改成模拟agent请求就完事了,这个可以自行了解
这个东西并不复杂,就是基本原理而已,估计大伙都知道。献丑了哈哈哈。
1.为什么逆向技术可行。
注意,此逆向技术与软件逆向技术,有着本质上的区别。软件逆向是分析出原来的代码逻辑。
而API逆向只是思考如何伪装为原来的客户端/浏览器,来请求服务器。让服务器认为是“自己人”而已
现行大概分为两种逆向技术,一种是网页逆向,一直是agent工具逆向。
其实两种逆向技术差不多,本质上都是伪装为客户端请求服务器
抛砖引玉一下,先说说网页逆向
2.网页逆向
如果我们使用浏览器请求,那么打开F12,就能看到浏览器的请求数据。
当我们使用工具请求而不是浏览器请求,如何让网站以为是“自己人”呢?这就需要一系列伪装技术。现在浏览器领域,有很多爬虫技术,我们可以凑合用用。
selenium, undetected_chromedriver, drissionpage 这些现成工具就不介绍了,就当大家已经了解了。关键就在于绕过目标系统的 浏览器完整性检测。
此外,也可以使用BrowserMob Proxy 生成 HAR 文件来获取目标数据格式,
HAR是记录浏览器与服务器交互数据的文件格式,一般是用来性能分析和问题调试的。但是我们可以滥用这个来玩爬虫与逆向。
3.逆向目标是什么?
所谓API逆向,就是把目标网站的api,让软件直接通过v1系列的api使用。而实现这个目标主要分为两部分:1.软件接收/v1/的api请求,2.把请求包装为目标网页的数据格式发给网页。
而回来的路径也相同,1.网页返回数据,软件解析数据,并包装为/v1/的api接口返回给客户端。
4.网页模拟入门
既然知道了关键在于伪装为网页的“自己人”请求的模拟,我们首先就要先看看网页上的请求是怎么样的,最简单的方法就是打开F12,访问一下并抓个包看看。
首先我们打开某个chat ai的网页,输入任意聊天内容,让浏览器截获并记录请求

可以看到这里的请求路径,请求格式。以及响应格式。
那么我们就需要模拟我自己人,我们浏览器可以看到这些请求头
```
POST /api/chat HTTP/2
Host: chat.xxxx.xx.con
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:140.0) Gecko/20100101 Firefox/140.0
Accept: text/event-stream
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate, br, zstd
Referer: https:/chat.xxxx.xx.con/
Content-Type: application/json
Content-Length: 4505
Origin: https://chat.xxxx.xx.con
Connection: keep-alive
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: cors
Sec-Fetch-Dest: empty
```
> 注:为了避免敏感举例问题,上面的chat.xxxx.xx.con是打码网址。
为了避免被服务器发现并禁止我们访问,我们就需要模拟上述请求头(当然使用HAR文件是最简单的,但是这里为了让大家看的更清楚。我们手工举例)。
常见chat网址,都有浏览器完整性检查。为了绕过完整性检查,上面说的 undetected_chromedriver, drissionpage就派上用场了。
下面我们以DrissionPage为例
使用ChromiumPage获取页面以及绕过检测,然后以SessionPage模拟api发送请求(后续其实可以不使用SessionPage了,直接让软件使用cookie与header,使用gp-http-client请求比较快)
ChromiumPage就这样用的,设置header与cookie请求
```python
from DrissionPage import ChromiumPage
page = ChromiumPage()
page.set.extra_headers({
'Authorization': 'Bearer xxx',
'X-Test': '123'
})
page.set.user_agent('Mozilla/5.0')
page.set.cookies({
'name': 'sessionid',
'value': 'abc123',
'domain': '.example.com'
})
page.get('https://example.com')
```
后续可以不通过ChromiumPage了,直接SessionPage请求就完事了。不过大多数都是直接使用golang写一个来请求。
SessionPage就这样请求,记得带上相同的cookie、header、user-agent。某些网址IP地址也存在cookie对应,这种要使用相同的代理IP
```
session = SessionPage()
session.set.cookies(cookies)
page.set.extra_headers({
'Authorization': 'Bearer xxx',
'X-Test': '123'
})
page.set.user_agent('Mozilla/5.0')
r = session.post(
'https://example.com/api/chat',
data={'a':1,'b':2}
)
print(r.text)
```
某些网址的参数长期不变,这种甚至都不需要ChromiumPage自动化请求,第一次人工抓包,后续直接请求就行了。
5.软件模拟/v1/chat/ 接口
这种难度低多了,基本上不需要像上面的网页逆向接口一样经常更新与换。基本稳定不变的。
```python
from flask import Flask, request, jsonify
import time
import uuid
app = Flask(__name__)
@app.route("/v1/chat/completions", methods=["POST"])
def chat_completions():
data = request.json
messages = data.get("messages", [])
model = data.get("model", "fake-gpt")
user_message = ""
if messages:
user_message = messages[-1].get("content", "")
reply = f"Echo: {user_message}"
response = {
"id": "chatcmpl-" + uuid.uuid4().hex[:24],
"object": "chat.completion",
"created": int(time.time()),
"model": model,
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
"content": reply
},
"finish_reason": "stop"
}
],
"usage": {
"prompt_tokens": 0,
"completion_tokens": 0,
"total_tokens": 0
}
}
return jsonify(response)
if __name__ == "__main__":
app.run(host="0.0.0.0", port=8080)
```
请求localhost:8080,模型选择model = data.get("model", "fake-gpt")这里设置的 就返回数据了。上面的这个例子,返回的回显的数据。实际上应该返回动态从网页那边返回的数据,
好了,差不多就是这样。不过提醒一点,现在的很多网页,都有额外的header或者cookie session做防护。要注意这一点不要漏了。
此外,逆向agent的方法与逆向网页差不多,就是“4.网页模拟入门”这个方法改一下,后续都不要改的,模拟网页改成模拟agent请求就完事了,这个可以自行了解