#Fiddler# HTTP的通信监控和回放:Fiddler抓包与Socket发包

#Fiddler# HTTP的通信监控和回放:Fiddler抓包与Socket发包

利用Fiddler抓包和Socket发包,并用Curl脚本统计响应时间,主要分为以下四个部分:

  • 工具的配置及工具的使用
  • 截获、修改、发送数据包
  • 统计网页和元素的响应时间
  • 需注意事项及待改进事项

任务

部署类似Microsoft PetshopWeb应用基本实例,开发性能测试小工具能截获基于IE浏览器与Web服务器的交互的数据包,修改数据包(比如简化起见,修改要搜索的关键字),再把修改后的内容使用多线程的方式发送到服务器。统计请求每个网页上主要元素(gif,css等)需要的时间,以及请求整个网页的时间。

提示:

  1. 在获取数据包的过程中要根据HTTP请求的特点,从原始的数据包中过滤出HTTP的数据包。找到提交的“搜索的关键字”,将其替换成其它字符。

  2. 发送数据包使用Socket,可以参考网络编程的资料。

  • 方法
    • 截获数据包
    • 修改数据包
    • 发送数据包
    • 记响应时间
  • 手段
    • 用Fiddler截获
    • 用Python修改
    • 用Socket发送
    • 用Fiddler查看
  • 验证
    • 可用性
    • 易用性
    • 并发性

工具的配置

安装工具

Fiddler下载地址

导入证书

Decrypt to capture Https

Decrypt to capture Https

勾选解码

GZip encoding is default in Fiddler

过滤保存

手动

Set filters

Save sessions

脚本

Customize Rules

Edit scripts

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
if (oSession.fullUrl.Contains("baidu.com")) {
// for(var key in oSession.oRequest.headers) {
// if('Referer' === key) {
if(oSession.oRequest.headers['Referer'].indexOf("&wd=") != -1) {
var fso;
var file;
fso = new ActiveXObject("Scripting.FileSystemObject");
file = fso.OpenTextFile("E:\\MyPrograms\\fiddler_sessions\\Session" + new Date().getTime() + ".txt", 8 ,true, true);
// file.writeLine("Request url: " + oSession.url);
file.writeLine("Request header:" + "\n" + oSession.oRequest.headers);
// file.writeLine("Request body: " + oSession.GetRequestBodyAsString());
file.writeLine("\n");
file.close();
}
// }
// }
}

设置断点

手动

Set Breakpoints

命令

  • 在左下角黑框框中输入命令
    • 停止断点:bpu
    • 开始断点:bpu $host

工具的使用

Statistics

Statistics

Filters

Filters

Inspectors

Inspectors

Composer

Composer

AutoResponder

AutoResponder

截获数据包

图形界面

  • 使用图形界面或编程脚本应用过滤
  • 点击左下角 Capturing或空白处 停止或开始截获数据包
  • 使用Statistics查看时间,使用Inspectors查看内容
  • 使用图形界面或编程脚本保存会话

修改数据包

程序脚本

对于手动保存的会话

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# 替换请求中的搜索字段
def get_ref(file, cont):
with open(file, encoding='utf-8') as f:
lines = f.readlines()
for line in lines:
if 'Referer' in line:
start = line.find("&wd=")
end = line.find("&rsv_pq=")
old_str = line[start+4:end]
new_str = parse.quote(cont)
line = line.replace(old_str, new_str)
return line


# 重新拼装需发送的报文
def get_req(file, cont):
msg = ''
with open(file, encoding='utf-8') as f:
lines = f.readlines()
for line in lines:
if 'GET' in line:
line = 'GET ' + get_ref(file, cont)[9:-1] + ' HTTP/1.1'
if 'Referer' in line:
line = get_ref(file, cont)
if 'Accept-Encoding' in line:
continue
line = line.strip('\n') + '\r\n'
msg += line
msg = bytes(msg, encoding="utf8")
return msg

对于自动保存的会话

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# 替换请求中的搜索字段
def get_ref(file, cont):
with open(file, encoding='utf-16') as f:
lines = f.readlines()
for line in lines:
if 'Referer' in line:
start = line.find("&wd=")
end = line.find("&rsv_pq=")
old_str = line[start+4:end]
new_str = parse.quote(cont)
line = line.replace(old_str, new_str)
return line


# 重新拼装需发送的报文
def get_req(file, cont):
msg = ''
with open(file, encoding='utf-16') as f:
lines = f.readlines()
for line in lines:
if 'Request header:' in line:
continue
if 'GET' in line:
line = 'GET ' + get_ref(file, cont)[9:-1] + ' HTTP/1.1'
if 'Referer' in line:
line = get_ref(file, cont)
if 'Accept-Encoding' in line:
continue
line = line.strip('\n') + '\r\n'
msg += line
msg = bytes(msg[:-4], encoding="utf8")
return msg

发送数据包

Fiddler

使用WebForms

  • 使用图形界面或编程脚本应用过滤
  • 使用图形界面或运行命令设置断点
  • 对应报文ARequest WebForms内修改“搜索关键字”
  • 点击 Break on Response 将修改后的 对应报文A 发送到Fiddler
  • 对应报文BRequest WebForms内查看“搜索关键字”
  • 点击 Run to Completion 将修改后的 对应报文B 发送到Server

使用Composer

  • 保存会话Request请求头部
  • 在记事本内修改“搜索关键字”
  • 在Composer内发送请求报文

Socket

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
if __name__ == '__main__':
# 读取信息
file = input("file:")
cont = input("cont:")

# 套接字连接服务端
s = ssl.wrap_socket(socket.socket())
s.connect(('www.baidu.com', 443))

# 发送修改后的请求
s.send(get_req(file, cont))

# 缓存服务端的响应
buffer = []
while True:
d = s.recv(1024)
if d:
buffer.append(d)
else:
break
res = b''.join(buffer)

# 客户端关闭套接字
s.close()

# 保存响应
header, html = res.split(b'\r\n\r\n', 1)
print(header.decode('utf-8'))
with open(cont + '.html', 'wb') as f:
f.write(html)

记响应时间

Fiddler

PyCurl

Urllib

Request

实例的演示

Flowchart

  • [仅使用Fiddler抓包、修改、发包](录屏链接To be continue…)
  • [Fiddler抓包+Python修改+Socket发包](录屏链接To be continue…)

需注意事项

报文格式

  • 无论使手动还是脚本保存会话的请求报文,都需要注意每个属性是否以 \r\n 结尾,最后属性是否以 \r\n\r\n 结尾
  • 遇到 HTTP 400 Bad Request 响应仔细检查报文格式是否正确

编码问题

  • 注意保存会话的编码格式,手动保存使用编码格式 utf-8 ,脚本保存使用编码格式 utf-16
  • Socket发送报文和接受报文都需要二进制数据
  • Fiddler默认使用GZip格式压缩,在发送请求报文时为确保响应主题非乱码,应该去除 Accept-Encoding: gzip, deflate 这行属性

端口问题

  • Socket通信需要知道主机地址及其端口号
    • Fiddler Sessions或Inpectors可知主机地址及其端口号
    • 保存的TCP报文(使用Wireshark)可知主机地址及其端口号
    • 保存的HTTP/HTTPS报文(使用Fiddler)仅知主机地址,已知常用端口:HTTP为80/HTTPS为443

请求变化

  • Break on ResponseRun to Completion 对应会话并不相同

待改进事项

  • 优化过滤会话和替换内容脚本(正则表达式)
  • 发送响应回浏览器(Socket向其它进程发报文)
  • 持续化、多线程抓包、修改、发包(多线程编程)

Comments

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×