一个包为hearer+body(格式为header+两个分割符+body)其中hearer的一个字段Content-Length的值为body的长度(包含\n\r0等字节)然后加上后端解析即为我拼接上去的(要走私的包)
一个 HTTP 请求由 headers 和 body 组成,格式为:
headers + \r\n\r\n + body
其中,headers 中的 Content-Length 字段的值,必须等于 body 部分的原始字节数(包括 \r、\n、0、空格、字母等所有字节)。
在 CL.TE 型请求走私中,我们将一个完整的 HTTP 请求(即"要走私的包")拼接在 body 末尾;前端服务器依据 Content-Length 截断请求,而后端服务器依据 Transfer-Encoding: chunked 解析 body,从而将拼接的部分当作下一个请求执行。
然后分为两种情况

直接使用模板(第一种的模板)
第二种直接使用拼接后端数据包(需要重新计算长度)

那么先按照第一种来







第二种方法
TE.CL 走私的本质就是:让后端解析两个请求,而前端只看到一个。
后端通过不断读取 "长度标签 + 数据 + \r\n",直到遇到 "0\r\n\r\n",就知道 body 结束了。


🔍 后端解析过程(像机器人一样一步步读)
▶ 第 1 步:读第一个 chunk 的"大小标签"
- 从 body 开始读,直到遇到
\r\n - 读到:
3\r\n - 解析
"3"→ 十六进制 = 3 - ✅ 结论:接下来有 3 个字节的数据
▶ 第 2 步:读 3 个字节的数据
- 接下来 3 个字节是:
A、B、C - ✅ 读完,正好 3 字节
▶ 第 3 步:验证 chunk 结束标记
- chunk 规范要求:数据后必须跟
\r\n - 下两个字节是:
\r、\n - ✅ 匹配!这一块 chunk 合法结束
▶ 第 4 步:读下一个 chunk 的"大小标签"
- 继续读,直到下一个
\r\n - 读到:
0\r\n - 解析
"0"→ 十六进制 = 0 - ✅ 结论:这是最后一个 chunk,body 到此结束!
💡 这就是关键!
0表示"没有更多数据了"
▶ 第 5 步:读最终的空行(协议要求)
- chunked 编码规定:
0\r\n后必须跟一个空行\r\n - 下两个字节是:
\r、\n - ✅ 匹配!整个 body 合法结束
▶ 第 6 步:body 结束!剩下的数据是什么?
- 当前已读字节数:13(正好是整个 body)
- TCP 流中下一个字节 是:
G(来自GET /admin...) - 后端认为: "我已经处理完一个完整的 HTTP 请求了。
现在收到的新数据
GET /admin...,一定是下一个请求!"
→ 于是,后端执行 GET /admin HTTP/1.1!




由于包的格式为header+两个字节(\r\n)+body
所以在计算时直接忽略掉中间的(\r\n)然后计算即可(所以是18) 
人话就是套这个公式
(其中1-6步都要换行)
1.在原本的数据包的包头添加Transfer-Encoding: chunked\r\n
2.然后添加\r\n(header结束标志)
3.然后是16进制原始数据的长度+\r\n
4.然后是原始数据+\r\n
5.添加0\r\n\r\n
6.要走私的请求
7.最后更新原本包的Content-Length为
原始数据的字节长度 + 长度标签的字节数(长度标签的字节数 = 把原始数据的字节长度转成十六进制后,这个十六进制字符串有几个字符,就是几字节)+ 9
第七步直接上程序
# -*- coding: utf-8 -*-
"""
极简 TE.CL Content-Length 计算器
功能:输入原始数据 → 输出 CL = len(utf8) + len(hex(len)) + 9
"""
import tkinter as tk
from tkinter import ttk, messagebox
class SimpleCLCalculator:
def __init__(self, root):
self.root = root
self.root.title("TE.CL Content-Length 计算器")
self.root.geometry("500x220")
self.root.resizable(False, False)
self.create_widgets()
def create_widgets(self):
# 说明文字
tk.Label(
self.root,
text="输入原始 POST body(如 q=admin),自动计算:\n"
"Content-Length = 字节长度 + 十六进制标签长度 + 9",
font=("微软雅黑", 10),
fg="black",
justify="left"
).pack(pady=10)
# 输入框
tk.Label(self.root, text="原始数据:", font=("微软雅黑", 10)).pack(anchor="w", padx=30)
self.entry = tk.Entry(self.root, width=60, font=("Consolas", 10))
self.entry.pack(pady=5, padx=30)
self.entry.focus()
# 按钮
ttk.Button(
self.root,
text="计算 Content-Length",
command=self.calculate
).pack(pady=10)
# 结果显示
self.result_var = tk.StringVar()
self.result_label = tk.Label(
self.root,
textvariable=self.result_var,
font=("Consolas", 14, "bold"),
fg="green"
)
self.result_label.pack(pady=10)
def calculate(self):
raw = self.entry.get()
if not raw:
messagebox.showwarning("输入为空", "请输入原始数据!")
return
try:
# 1. 计算 UTF-8 字节长度
data_len = len(raw.encode('utf-8'))
# 2. 转十六进制(去掉 '0x',小写)
hex_tag = hex(data_len)[2:]
# 3. 长度标签字节数 = 十六进制字符串长度
tag_len = len(hex_tag)
# 4. 最终结果
cl = data_len + tag_len + 9
# 显示结果
self.result_var.set(f"Content-Length = {cl}")
except Exception as e:
messagebox.showerror("错误", f"计算失败:{str(e)}")
if __name__ == "__main__":
root = tk.Tk()
app = SimpleCLCalculator(root)
root.mainloop()




