配置Mysql

sudo mysql -u root //第一次可以直接进入
alter user 'root'@'localhost' identified by '123456';
create database usr;

配置PHP

进入目录:cd /etc/php/8.2/apache2

执行:sudo vim +904 php.ini
将这行代码前面的注释去除:extension=mysqli

进入到目录:cd /var/www/html/
创建以下文件:vim TestConn.php
TestConn.php测试文件代码

<?php
// 启用错误报告
error_reporting(E_ALL);
ini_set('display_errors', 1);

// 数据库配置
$servername = "localhost";
$username = "root";
$password = "123456"; // 替换为实际密码,修改密码命令,alter user 'root'@'localhost' identified by '123456';
$dbname = "usr"; // 替换为实际数据库名,需要自己创建,命令,create database usr;

try {
    // 创建连接
    $conn = new mysqli($servername, $username, $password, $dbname);
    // 检查连接
    if ($conn->connect_error) {
        throw new Exception("连接失败: " . $conn->connect_error);
    }
    // 设置字符集
    if (!$conn->set_charset("utf8mb4")) {
        throw new Exception("字符集设置失败: " . $conn->error);
    }
    echo "MySQL连接成功!服务端版本: " . $conn->server_version;
    // 关闭连接
    $conn->close();
} catch (Exception $e) {
    die("数据库错误: " . $e->getMessage());
}
?>

配置apache2服务器

进入目录:cd /etc/apache2/
修改文件:sudo vim +174 apache2.conf
直接添加以下内容

     LoadModule php_module modules/libphp.so

测试

先执行这个DROP掉系统的RST包sudo iptables -A OUTPUT -p tcp --tcp-flags RST RST -j DROP

from scapy.all import *
import random
import time

target_ip = "127.0.0.1"
target_port = 80
source_port = random.randint(1024, 65535)

ip = IP(dst=target_ip)
syn = ip / TCP(sport=source_port, dport=target_port, flags="S", seq=1000)
syn_ack = sr1(syn, timeout=2, verbose=0)

if not syn_ack or not syn_ack.haslayer(TCP):
    print("未建立TCP连接。")
    exit()

server_seq = syn_ack[TCP].seq
server_ack = syn_ack[TCP].ack

# 第三次握手
ack = ip / TCP(sport=source_port, dport=target_port, flags="A", seq=server_ack, ack=server_seq + 1)
send(ack, verbose=0)

# 构造HTTP请求
http_get = "GET /TestConn.php HTTP/1.1\r\nHost: 127.0.0.1\r\nConnection: close\r\n\r\n"
http_payload = http_get.encode("UTF-8")
get_request = ip / TCP(sport=source_port, dport=target_port, flags="PA", seq=server_ack, ack=server_seq + 1) / http_payload
send(get_request, verbose=0)

# 接收所有响应数据段
response_data = b""
seq = server_ack
timeout = time.time() + 5  # 最多等待5秒

while time.time() < timeout:
    pkt = sniff(filter=f"tcp and src host {target_ip} and port 80", count=1, timeout=1)
    if not pkt:
        continue
    tcp = pkt[0][TCP]
    if tcp.sport == target_port and tcp.dport == source_port and tcp.haslayer(Raw):
        payload = bytes(tcp[Raw].load)
        response_data += payload
        # 发送ACK回执
        ack_pkt = ip / TCP(sport=source_port, dport=target_port, flags="A",
                           seq=tcp.ack, ack=tcp.seq + len(payload))
        send(ack_pkt, verbose=0)

# 打印HTTP响应
#if response_data:
#    print("=== 服务器完整响应内容 ===")
#    try:
#        print(response_data.decode("utf-8", errors="ignore"))
#    except Exception:
#        print(response_data)
#else:
#    print("未接收到HTTP响应数据。")

老师的http测试文件


from scapy.all import *

import random



target_ip = "172.17.15.200"

target_port = 80

ip = IP(dst=target_ip)

syn = ip / TCP(sport=1024, dport=target_port, flags="S", seq=1000)

syn_ack = sr1(syn, timeout=2, verbose=0)
server_seq = syn_ack[TCP].seq

server_ack = syn_ack[TCP].ack

ack = ip / TCP(sport=1024, dport=target_port, flags="A", seq=server_ack, ack=server_seq + 1)
send(ack, verbose=0)
http_get = "GET /TestConn.php HTTP/1.1\r\nHost: 127.0.0.1\r\nConnection: close\r\n\r\n" 

http_payload = http_get.encode('utf-8')
get_request = ip / TCP(sport=1024, dport=target_port, flags="PA", seq=server_ack, ack=server_seq + 1) /Raw(load=http_payload)

response = sr1(get_request, timeout=5, verbose=0)

大全套代码

#!/usr/bin/env python3
# scapy_http_capture.py
from scapy.all import *
import random
import time
import sys

target_ip = "127.0.0.1"
target_port = 80
path = "/TestConn.php"
source_port = random.randint(20000, 40000)
timeout_total = 8  # 最大等待秒数

def decode_chunked(data: bytes) -> bytes:
    out = b""
    i = 0
    while True:
        # 找到行结束
        rn = data.find(b"\r\n", i)
        if rn == -1:
            break
        line = data[i:rn].strip()
        try:
            size = int(line.split(b";",1)[0], 16)
        except:
            break
        i = rn + 2
        if size == 0:
            # 跳过尾部可能的 trailer
            # 找到最后的 \r\n\r\n
            trailer_idx = data.find(b"\r\n\r\n", i)
            return out
        out += data[i:i+size]
        i += size + 2  # 跳过 chunk-data 和 CRLF
    return out

def assemble_payloads(payload_map, start_seq):
    # payload_map: {seq: bytes}
    if not payload_map:
        return b""
    seqs = sorted(payload_map.keys())
    cur = seqs[0]
    assembled = b""
    for s in seqs:
        p = payload_map[s]
        if s > cur:
            # 有 gap:填补不可见数据(跳过)
            cur = s
        if s < cur:
            # 有重叠,从偏移处拼接
            offset = cur - s
            if offset < len(p):
                assembled += p[offset:]
                cur += len(p) - offset
        else:
            assembled += p
            cur += len(p)
    return assembled

def parse_http(raw: bytes):
    # split headers / body
    hdr_end = raw.find(b"\r\n\r\n")
    if hdr_end == -1:
        return None, raw
    headers_raw = raw[:hdr_end].decode("iso-8859-1", errors="ignore")
    body = raw[hdr_end+4:]
    # parse status + headers
    lines = headers_raw.split("\r\n")
    status_line = lines[0]
    headers = {}
    for l in lines[1:]:
        if ":" in l:
            k, v = l.split(":", 1)
            headers[k.strip().lower()] = v.strip()
    # handle chunked
    if headers.get("transfer-encoding","").lower() == "chunked":
        body_decoded = decode_chunked(body)
    else:
        # respect content-length if present
        body_decoded = body
    return (status_line, headers), body_decoded

def main():
    conf.verbose = 0
    ip = IP(dst=target_ip)
    syn = ip / TCP(sport=source_port, dport=target_port, flags="S", seq=1000)
    print("[*] 发送 SYN,发起三次握手...")
    syn_ack = sr1(syn, timeout=2, verbose=0)
    if not syn_ack or not syn_ack.haslayer(TCP):
        print("[-] 未收到 SYN-ACK,终止。")
        sys.exit(1)

    server_seq = syn_ack[TCP].seq
    server_ack = syn_ack[TCP].ack
    # 第三次握手 ACK
    ack = ip / TCP(sport=source_port, dport=target_port, flags="A",
                   seq=server_ack, ack=server_seq + 1)
    send(ack, verbose=0)
    print("[+] 三次握手完成。")

    # 发送 HTTP GET //如需要发送HEAD,把下面的GET改掉即可
    http_get = f"GET {path} HTTP/1.1\r\nHost: {target_ip}\r\nConnection: close\r\nUser-Agent: scapy-test\r\n\r\n"
    http_payload = http_get.encode("utf-8")
    get_request = ip / TCP(sport=source_port, dport=target_port, flags="PA",
                           seq=server_ack, ack=server_seq + 1) / http_payload
    print("[*] 发送 HTTP GET 请求 ->", path)
    send(get_request, verbose=0)

    # 捕获来自服务器的包,直到收到 FIN 或 超时
    payload_map = {}  # seq -> bytes
    saw_fin = False
    start_time = time.time()
    print("[*] 开始 sniff 捕获来自服务器的数据包(显示 packet.show())...")
    while True:
        if time.time() - start_time > timeout_total:
            print("[*] 超时,停止捕获。")
            break
        pkts = sniff(iface="lo",filter=f"tcp and src host {target_ip} and port {target_port}", count=1, timeout=1)
        if not pkts:
            continue
        pkt = pkts[0]
        # 实时展示包结构
        print("\n--- 捕获到包,结构如下 ---")
        pkt.show()
        # 检查是否为目标方向与端口
        if not pkt.haslayer(TCP):
            continue
        tcp = pkt[TCP]
        # 只处理发送到我们 source_port 的回应
        if tcp.dport != source_port:
            continue
        # 若有 Raw 层则收集载荷
        if pkt.haslayer(Raw):
            data = bytes(pkt[Raw].load)
            payload_map[tcp.seq] = data
            # 发送 ACK 回执给服务器(告诉服务器我们已收到)
            ack_pkt = ip / TCP(sport=source_port, dport=target_port,
                               flags="A", seq=tcp.ack, ack=tcp.seq + len(data))
            send(ack_pkt, verbose=0)
        # 如果看到 FIN 或 RST 表示连接结束
        if tcp.flags & 0x01 or tcp.flags & 0x04:
            saw_fin = True
            print("[*] 观察到 FIN/RST,连接结束信号。")
            break

    assembled = assemble_payloads(payload_map, None)
    if not assembled:
        print("[-] 未捕获到任何 HTTP 负载 (Raw)。")
        print("提示:若在本机 loopback 上运行仍看不到数据,确保以 root 运行,或绑定实际网卡 IP 再试。")
        sys.exit(0)

    # 尝试解析 HTTP(头 + body)
    parsed, body = parse_http(assembled)
    print("\n=== 原始重组后的字节流(前 4096 字节展示) ===")
    print(assembled[:4096].decode("utf-8", errors="ignore"))
    if parsed is None:
        print("\n[-] 无法解析 HTTP headers,直接输出 body(尝试 utf-8 解码):")
        try:
            print(body.decode("utf-8", errors="ignore"))
        except:
            print(body)
        sys.exit(0)

    status, headers = parsed
    print("\n=== HTTP 状态行 ===")
    print(status)
    print("\n=== HTTP Headers ===")
    for k, v in headers.items():
        print(f"{k}: {v}")
    print("\n=== HTTP Body (utf-8 解码,errors='ignore') ===")
    try:
        print(body.decode("utf-8", errors="ignore"))
    except:
        print(body)

if __name__ == "__main__":
    main()

效果图

需要打开lo接口
浏览器
image

wireshark
image

posted on 2025-10-15 19:30  suiseiseki  阅读(37)  评论(0)    收藏  举报