HTTP协议入门与Fiddler抓包

HTTP协议入门与Fiddler抓包

坚果 Jimbowhy 前后端脚本编程轻松篇集合文章:

HTTP 基础

关于HTTP协议的完整资料在RFC2616, 这个文档事无巨细地记录相关内容, RFC 全称 Request For Comments.

先不必理会HTTP是基于TCP/IP协议的应用层协议, HTTP可以简单理解一个约定, 一个用文本进行约定的协议, 它本来面目就很容易看得懂, 只要有记事本就可以. 典型的HTTP是在浏览器和服务器之间使用的, 浏览器作为客户端, 向服务器发送请求, 服务器接收到请求后进行响应. 比如我要打开树莓派的官方网站, 那么首先就要在浏览器的地址栏上输入网址, 然后确认. 浏览器则根据地址构造一个HTTP协议包, 然后通过TCP/IP联网发送出去. 一个常见的HTTP请求包如下:

GET https://www.raspberrypi.org/ HTTP/1.1
Host: www.raspberrypi.org
Connection: keep-alive
Upgrade-Insecure-Requests: 1
User-Agent: Chrome/55.0.2883.87
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.8,en;q=0.6
Cookie: _ga=GA1.2.1434384935.1525184955; _gid=GA1.2.2106067700.1525184955

这是一个典型的只有头部的HTTP协议包, 虽然一个完整包应该包含协议头和数据部分, 但数据部分是可选的. HTTP协议头的第一行一定是一个单词开头表示一个请求动作, 常见的如POST/GET, 这两种方法也是网页在提交表单时常用的. 动作后面又跟着服务器地址, 地址后是协议版本号, 通常是 HTTP/1.1. 第二行是服务器主机域名, 服务器一个IP地址可以配置运行多个网站, 这个域名在服务器端就称为虚拟主机. 根据这个域名, 服务器会将接受到的请求, 网站默认端口是80, 发送到相应的网站程序, 交由程序来响应客户端的请求. 如以下是来自树莓派服务器的响应:

HTTP/1.1 200 OK
Date: Tue, 01 May 2018 16:42:40 GMT
Server: Apache/2.4.10 (Debian)
Link: <https://www.raspberrypi.org/wp-json/>; rel="https://api.w.org/"
Link: <https://www.raspberrypi.org/>; rel=shortlink
Vary: Accept-Encoding
Content-Security-Policy: upgrade-insecure-requests; default-src https: data: 'unsafe-inline' 'unsafe-eval'; report-uri https://e46468ffd14a954844abf8fe208613d8.report-uri.com/r/d/csp/enforce
X-Clacks-Overhead: GNU Terry Pratchett
X-Served-By: piautoblog2
Content-Length: 37949
Connection: close
Content-Type: text/html; charset=UTF-8

<!DOCTYPE html>
......

这里就是一个完整的HTTP协议包, 含有HTTP协议头和数据两部分, 数据只显示一部分, 其余的省略. 协议头和数据以两个换行符分割, <!DOCTYPE html> 这句开始到结束部分就是数据, 因为请求的是网页, 所以返回的就是HTML页面, 如果请求的是图像, 那这里的数据就是二进制数码. 协议头还有其他一些字段设置, 如 Server 表示服务是什么软件搭建的, 这里是 Apache/2.4.10, Debian 则是linux操作系统. 常用的还有 lighttped, nginx, iis, tomcat 等等. Content-Length 这个字段表示数据部分的字节数, Content-Type 表示数据内容如格式, 即HTML文本, 并且按 UTF-8 编码.

这两个步骤就是一个完整的HTTP通信, 这样的一种发起请求-响应结束的连接称之为短连接, 这就是所谓的无状态连接. 最早期的设计就是这样简单的需求, 根本不需要什么状态, 只要能在地球另一端看到网页就是 Perfect. 可是后来世界变了, 网站功能不再是一个只提供网页的服务器了. 网站变得更像是一个完整的程序了, 它需要为通过浏览器连接服务器的用户提供更复杂的功能, 比如说网购, 如果还像以前那样, 浏览器发起请求-服务器响应结束, 当用户在次进入服务器是, 服务器根本不知道是谁, 是不是刚才的那位用户, 因为服务器根本没有几录用户的相关信息.

一个解决方法是在客户端使用 Cookie 或在服务器端使用 Session, 它们的产生都是为了解决无状态连接的, 每一个用户通过一个ID, 叫 SessionID 来实现连接状态管理. 客服端使用 Cookie 又有很大的局限, 因为用户一个不爽就可以关掉不用, 这时只在服务端记录 Session 也没用, 因为客户端没有发送关联的 Cookie 到服务器, 网站程序根本无法知道是谁在请求网页, 这种情况下只是通过URL地址来传输 SessionID. 服务器想给客户端设置 Cookie 时, 会在协议头添加一个 Set-Cookie 字段, 浏览器收到后会将 Cookie 值保存下来, 在下次发出请求时将 所有 Cookie 信息回传到服务器, 这个过程就可以实现连接状态的保持:

注意看请求包的协议头, Connection 字段指定了一个 keep-alive 值, 也就是浏览器向服务器表达在TCP/IP层保持连接的意愿, 而服务器返回的是 Connection: close, 告诉客户端, 连接已经关掉了. 从客户端来看, 保持连接是正确的做法, 请求一个网页, 很大可能还要一堆的资源文件如JS脚本, CSS样式表, 其他一些图片才能完成网页的渲染, 保持连接更省资源. 而服务器可以完全不必理会, 我行我素, 直接关掉连接, 客户端只好在重新发起连接, 请求其他资源文件. 所以, 这一点来看, HTTP是一个不严格的应用协议.

关于POST和GET方法, 在提交网页表单时更能体现差别. GET方法提交表单, 表单的数据会被编码到URL上, 作为请求地址的一部分, 也就是说浏览页面的用户可以直接在地址栏看到数据. 而POST方法则不是, 它会将表单数据编码到HTTP协议包的数据部分, 在表单的数据量大时就必须要这种方式来处理, 因为URL是有长度限制的.

关于协议头字段 Referrer, HTTP 协议中有一个字段用来表示当前请求的来源,于上世纪 90 年代提出来,当时把这个请求头叫做 Referer,并最终写进了 RFC1945,即 HTTP/1.0 协议. 这个拼写是错误的, 正确的是 Referrer 即引荐者. 当这个错误被发现时,已经被大量使用各大网站社区了, 修改它似乎成本很高. 于是, 这个误用就延续至今, 下面这段描述来自于 RFC2616,也就是著名的 HTTP/1.1 协议:

The Referer[sic] request-header field allows the client to specify, for the server's benefit, the address (URI) of the resource from which the Request-URI was obtained (the "referrer", although the header field is misspelled.)via

Fiddler工作原理

MITM攻击,即中间人攻击(Man-in-the-middle-attacks,简称:MITM攻击),是一种电脑黑客的攻击模式。在 client 发出的请求、web server 返回数据之间,布置一个代理服务器 proxy server 进行转发,这个 proxy server 就起到了一个 middle man 的作用,Fiddler 就是充当这个中间人,代理设置在菜单 Tools -》Fiddler Options -》Connections,打开Fiddler的抓包功能后,它会自动设置WinINET,将流量路由到Fiddler的代理服务器上来。

Fiddler主界面主要分为三块, 上面是标准的菜单区, 左侧是请求列表, 右侧是主功能区, 选择一个请求, 然后选择一个功能如 Inspector, 它就会对请求进行分析.

Inspector 提供了多种视图, Headers 用来显示请求和响应的HTTP协议头部信息. SyntaxView 则显示语法高亮, 如 HTML, CSS, XML, Scripts 等内容, 所以在响应头上使用. WebForm 视图则是将POST/GET提交的表单以表格形式显示出来. HexView 非常有用, 它可以将完整的 HTTP 协议包以十六进制数码显示出来, 这对分析 HTTP 协议很有必要. 与之相似的 Raw 视图则把 HTTP 协议包当字符串来显示, 假设请求响应的二进制文件等内容, Raw 视图就够呛, 如果内容很多, Fiddler 突然就会卡了. WebView 和 ImageView 则是将响应内容当 HTML 和图片来显示. JSON 视图可以将响应的内容按树形视图显示, 如果内容是 JSON 格式.

除了 Inspector 这个主要功能, Fiddler 还有 HTTP 协议包构造器 Composer, 可以用他来构造出任意的 HTTP 请求包, AutoResponder 是 Composer 的加强版, 通过制定规则, 可以实现自动响应客户端的请求. 此外还有统计功能 Statistics, 日志记录 Log, 过滤器 Filters 等.

要开始抓包, 可以按下快捷键 F12, 或界面左下角的区域点击一下, 又或者在文件菜单选择 Capture Traffic.

提示 Fiddler 右下角的 Quickexec 使用, 这是一个命令行工具, 可以通过快捷键 Alt+Q 激活, 然后快捷键 Ctrl+I 可以将当前选中的 Session 的地址粘贴到这里, 确认就可以在浏览器打开. 如果 Fiddler 不是处于激活状态, 全局快捷键 CTRL+ALT+F 可以激活 Fiddler.

?sometext: 查找URL中含有 sometext 的 Session

>size: 选择响应内容字节数大于size的 sessions, 类似的还有 <size, 可以使用k做单位

=status: 选择指定状态 Session
=method: 选择指定请求方法的 Session
    =301 <-- Select 301 redirect responses
    =POST <-- Select POST requests

@host: 选择指定主机的 Session
    @msn.com <-- Select www.msn.com, login.msn.com, etc

bold: 粗体标记后续URL包含指定字符串的 sessions 
    bold /bar.aspx
    bold        <-- Call with no parameter to clear

bpafter: 设置断点 RequestURI 包含指定字符串时终断
    bpafter /favicon.ico 
    bpafter        <-- Call with no parameter to clear

bps: 按响应代码设置中断
    bps 404
    bps        <-- Call with no parameter to clear

bpv or bpm: 按请求方法POST/GET等设置断点
    bpv POST
    bpv        <-- Call with no parameter to clear

bpu: 按 URI 包含的字符串设置断点
    bpu /myservice.asmx
    bpu        <-- Call with no parameter to clear

cls or clear: 清除列表

dump: 以 zip 格式转储所有 Session 到C:\

g or go: 继续执行在中断状态下的 sessions

hide: 隐藏 Fiddler 到系统托盘

urlreplace: 对请求地址 URL 进行替换
    urlreplace SeekStr ReplaceWithStr
    urlreplace        <-- Call with no parameters to clear

show: 恢复显示 Fiddler 主界面通常用在 ExecAction.exe 条件触发

select MIME: 选择指定 Content-Type 类型的 Seesion

    select image
    select css
    select htm

select HeaderOrFlag PartialValue: 选择包含指定头信息的

    select ui-comments slow
    select ui-bold *     <-- unless preceded by a slash, * means any value
    select ui-comments \*     <-- Find comments with a *
    select @Request.Accept html     <-- Find requests with Accept: html
    select @Response.Set-Cookie domain <- Find responses that Set-Cookie on a domain

allbut 和 keeponly: 隐藏指定的 Session

    allbut xml
    allbut java

quit: Shutdown Fiddler.

!dns hostname: DNS查询, 结果记录在 LOG

    !dns www.example.com
    !nslookup www.example.com

!listen PORT [CERTHOSTNAME]: 侦听命令

    !listen 8889
    !listen 4443 localhost
    !listen 444 secure.example.com

Fiddler 热键

对于我这样经常离不开 Fiddler 的工作人员, 掌握 Fiddler 热键是非常有必要的. 系统级别的热键只有 CTRL+ALT+F, 它用来唤起 Fiddler, 无论当前在运行什么程序. 与之呼应的是 Ctrl+M 用来收缩 Fiddler 界面到系统托盘. 更多热键如下:

程序级别
Alt+Q - 激活 QuickExec 命令行
CTRL+F - 查找 sessions
CTRL+H - 视图跳转 Header Inspector
CTRL+T - 视图跳转 TextView Inspector
CTRL+Up - 选择上一个 session
CTRL+Down - 选择下一个 session

Session 列表

CTRL+A - 选择所有 sessions
CTRL+I - 反选 sessions
CTRL+X - 清除 Session 列表
R - 重发请求, Shift+R 指定重发次数
U - 无条件重发, 忽略缓存, Shift+U 指定次数
P - 定位到 Referer 引用页请求
C - 定位到引用当前URl的请求, 子请求
D - 查找重复请求
CTRL+1~6 标记六种颜色
CTRL+0 - 清除颜色标记
CTRL+C - 复制摘要
CTRL+U - 复制URL
CTRL+SHIFT+C - 复制协议头
F2 - 打开编辑模式
Backspace - 回到上次选择的 session
Delete - 删除选择的 sessions
Shift+Delete - 删除未选择的 sessions
Spacebar - 定位到选中的 session

协议头

CTRL+C - 复制协议头
CTRL+SHIFT+C - 复制协议头
ENTER - 编辑选中的头字段, 如果在编辑模式, 或在中断时
Delete - 删除选中的协议头字段, 如果在编辑模式
INSERT - 添加协议头字段

TextView

CTRL+G - 转到指定行
F3 - 查找下一个

HexView

CTRL+G - Goto byte

HTTP 数据包构造

实例:一个提交文件的表单,且只有一个文件。假设文件是文本,只有一行内容:

1234,4321

在浏览器中选好文件,并点击提交表单后,就会发送一个HTTP包,内容类似:

POST http://ci.yob1.hy.8188188.net:889/InportTxt/GetFile HTTP/1.1
Host: ci.yob1.hy.8188188.net:889
Connection: keep-alive
Content-Length: 188
Cache-Control: max-age=0
Origin: http://ci.yob1.hy.8188188.net:889
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 UBrowser/6.2.3964.2 Safari/537.36
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryOxZT0VqgpwJSg1hp
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Referer: http://ci.yob1.hy.8188188.net:889/InportTxt/GetFile
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.8,en;q=0.6
Cookie: ASP.NET_SessionId=ymg3yakf4qlz3azutcu4ivjf; kangle_runat=1; UserId=xxx; LoginName=xxx; NickName=k; DefaultCredit=196; UsedCredit=0; SuperCompanyName=sscmg; IsEnter=false; IsShowLottory=false; IsOddsUse=false; IsSingleBack=false; IsInheritTrading=false; IsInheritComm=false; SubNickName=RRR; PlayType=0; UserNo=67dffa7e1eec4edbbda51b97e530075b; CancelBet=3; SecondStopEarly=0; PeriodsNumber=20180422039; PeriodsID=280302; PeriodsStatus=1

------WebKitFormBoundaryOxZT0VqgpwJSg1hp
Content-Disposition: form-data; name="file"; filename="d.txt"
Content-Type: text/plain

1234,4321
------WebKitFormBoundaryOxZT0VqgpwJSg1hp--

注意最后面7行,用HEX码将那些不可见的字符表达出来就是:

0x0D, 0x0A, 0x0D, 0x0A, 
------WebKitFormBoundaryOxZT0VqgpwJSg1hp, 0x0D, 0x0A, 
Content-Disposition: form-data; name="file"; filename="d.txt", 0x0D, 0x0A,
Content-Type: text/plain, 0x0D, 0x0A, 
0x0D, 0x0A, 
1234,4321, 0x0D, 0x0A,
------WebKitFormBoundaryOxZT0VqgpwJSg1hp--, 0x0D, 0x0A 

每个0x0D, 0x0A就代表一个换行符,HTTP数据包的头部和数据部由两个换行符作分界。后面的是数据,这里一就那个上传到服务器的文件。表单是可以上传多个文件的,在HTTP头部的Content-Type里,multipart/form-data向服务器表明这一次提交的表单是包含文件的,服务器接受表单时就会根据Content-Type里指定的boundary,也就是----WebKitFormBoundaryOxZT0VqgpwJSg1hp来分割HTTP的数据部,以提取完整的文件。再看看HTTP数据部,注意boundary前面由多加了两个连字符--。两个boundary之间包含以个文件信息,注意,以两个换行符为界,前是文件基本信息,含有文件名、文件类型等,后面的就是文件内容。

构造表单是就要根据以上规则,boundary可以自行指定,只要不会和文件内容有一样的字符串就可以。

http数据包结构

使用Fiddler构造HTTP请求包

通过快捷键F9可以打开Composer,这就是构造器,最简单的操作就是将前面抓包得到的RAW数据拷贝过来,贴到Composer的RAW中。


http数据包构造

通过 Parsed 的 Upload file... 可以自动创建带文件上传的表单。

Composer 的升级版, AutoResponder 自动响应是非常有用的一个工具. 如何使用, 首先在请求列表选中想要拦截并自动响应的请求, 然后在面板选择 AutoResponder, 勾选 Enable rules, Unmatched requests passthrough, 再点击 Add Rule, Fiddler 会自动添加一条, URL映射规则, 匹配的URL请求就会被截取, 输出自动响应的内容.

在最下面的 Rule Editor 最下面的下拉框选择响应方式会或内容, 其中有许多内置模板文件, 比较好理解, 就是输出和HTTP响应代码匹配的数据, 文件位于 Fiddler 安装目录下的 ResponseTemplates. 例如 200 表示正常的响应, FiddlerGIf 是一个小提琴GIF文件:

200_FiddlerGif.dat
200_SimbpleHtml.dat
200_TransPixel.dat
204_NoContent.dat
302_Redirect.dat
303_RedirectWithGet.dat
304_NotModified.dat
307_RedirectWithMethod.dat
401_AuthBasic.dat
401_AuthDigest.dat
403_AuthDeny.dat
404_Plain.dat
407_ProxyAuthBasic.dat
502_Unreachable.dat

还有一些 * 号开头的设置, 表示这是一个动作 Action, 动作和前面的 QuickExec 是一个概念, bpafter 表示设置一个中断flag 表示设置程序标志, ui-backcolor 则对应程序界面的背景色. redir 表示产生一个跳转向应, script 表示执行一个 Fiddler 脚步方法:

*bpu
*bpafter
*exit
*drop
*reset
*delay:100
*ReplyWithTunnel
*CORSPreflightAllow
*flag:ui-backcolor=#FFD700
*header:HeaderName=NewValue
*redir:http://www.example.com
*script:FiddlerScriptFunctionName

后面还有一个 Find file ... 用来指定一个文件作为响应内容. 设置好响应后, 点击 Save 保存就可以生效了. 如果选择 Create New Response…, 则进入自定义响应, 点击 Save 后会弹出一个对话框,跟 Inspectore 的 Response 面板的布局一样的界面,在上面可以填写编辑响应数据. 这时可以直接将之前的响应内容拷贝一份过来再进行编辑. 改完保存, 返回到 AutoResponder 面板就可以看到响应内容变成类似 NEW_RESPONSE_18_38_10 这样的文件了. 这时在请求列表中选择配置号自动响应的请求, 按下快捷键 R 将请求重发, 来测试自动响应.

AutoResponder

特殊抓取设置

Windows平台下,VBS和JScript脚本是通过 WinHTTP 来实现联网的,默认情况下 Fiddler 只配置了WinINET,即浏览器默认使用的网络API。要实现对WinHTTP、XMLHTTP等API的抓包功能,需要再配置Windows的网络:

Windows Vista 或以上版本,Windows 7或早期的版本运行32bit、64bit的NETSH来对应配置32bit、64bit WinHTTP。:
netsh winhttp set proxy 127.0.0.1:8888

Windows XP 或以下:
proxycfg -p http=127.0.0.1:8888;https=127.0.0.1:8888

或强制 WinHTTP 使用 WinINET 的代理配置:
proxycfg -u

配置 PHP/cURL 应用程序使用 Fiddler 需要在发送请求前执行以下代码,ch 是 curl_init()的返回值: curl_setopt(ch, CURLOPT_PROXY, '127.0.0.1:8888');

或者在命令行中执行以下命令修改 curl 的API的代理:
curl --proxy 127.0.0.1:8888

完整的配置请参考Fiddler官方网站的Configuration...

抓取手机软件请求

我们需要查找自己电脑的 IP 地址,Fiddler主界面的右上角有一个Online按钮,鼠标放上去等一会就会出来包含IP地址的提示信息。 或在命令行下输入 ipconfig 就可以得到 Fiddler 运行的机器IP地址,代理服务器端口默认是8888。设置Fiddler的Connetions选项,勾选Allow remote computers to connect,重启软件配置才生效。

接下来,要在手机上设置代理以连接到 Fiddler,随便连接一个 WIFI,然后点击高级选项,手动设置代理,在主机名填入前面得到的IP地址,打开 Fiddler,就能看到手机上的给中请求数据了。如果手机程序没有使用代理,Fiddler就抓不到数据。

HTTPS抓包

要抓取走 HTTPS 的内容,Fiddler 必须解密 HTTPS 流量。浏览器需要检查数字证书,会发现会话遭到窃听。为了骗过浏览器,Fiddler 通过使用另一个数字证书重新加密经过Fiddler解密的 HTTPS 流量。Fiddler 被配置为解密 HTTPS 流量后,会自动生成一个名为 DO_NOT_TRUST_FiddlerRoot 的 CA 证书,并使用该 CA 颁发每个域名的 TLS 证书。若 DO_NOT_TRUST_FiddlerRoot 证书被列入浏览器或其他软件的信任 CA 名单内,则浏览器或其他软件就会认为 HTTPS 会话是可信任的、而不会再弹出“证书错误”警告。

首先,打开 Fiddler,在菜单栏中依次选择 【Tools】->【Fiddler Options】->【HTTPS】,勾上选项:

  • Capture HTTPS CONNECTs
  • Decrypt HTTPS traffic

勾上后,Fiddler 需要安装一个根证书。安装完后可以导出根证书到桌面,交给浏览使用。点击对话框的Action按钮,弹出选项操作:

  • Trust Root Certificate
  • Export Root Certificate to Desktop

DefaultCertficateProvider的Engine改成: MakeCert模式。

如果没有安装根证书,是不能通过 export root certificate to desktop 导出的,运行时就会报一个错误:

  • Fiddler “creation of the root certificate was not successful”

必要时可以手动生成并安装根证书,在fiddler目录下有一个makecert.exe,它是一个X509格式证书颁发工具,相当于OPENSSL,以下命令可以生成一个根证书,这个证书会安装在Windows系统中,通过证书管理工具可以查看:

makecert.exe -r -ss my -n "CN=DO_NOT_TRUST_FiddlerRoot, O=DO_NOT_TRUST, OU=Created by http://www.fiddler2.com" -sky signature -eku 1.3.6.1.5.5.7.3.1 -h 1 -cy authority -a sha1 -m 120 -b 09/05/2012
证书管理

在客户端安装证书,打开 Fiddler Echo Service 页面,默认地址是 http://ipv4.fiddler:8888/ 在页面上下载 FiddlerRoot certificate(文件名FiddlerRoot.cer)。导入证书进行安装这部分操作,Android和ios有一点不同。Android 可以连接到电脑上,从电脑上打开手机的内存卡,直接把证书导入SD卡中,这里可以直接使用下载好的 FiddlerRoot.cer。还有稍微麻烦的步骤,需要先设置手机锁屏密码、PIN码,安装证书时会提示。点击设置 => 安全 => 从SD卡安装 => 从内部存储空间中找到证书,点击安装即可。不同的厂商提供的Android系统操作上还有些差别,我的乐2为例,打开设置界面 => 指纹和密码 => 其他安全选项。这里可以选择从存储设备安装证书,或对已经安装好的证书进行管理。

ios可以在手机浏览器上登录邮箱,然后将证书发送到邮箱中,在手机上查看邮件,点击附件进行证书的安装即可接下去:设置->安全和隐私->从存储设备安装。另一个类似Fiddler的工具是Charles,可以在IOS平台上运行,证书下载页面是 http://chls.pro/ssl

HTTPS常见术语

TLS:传输层安全协议 Transport Layer Security的缩写
SSL:安全套接字层 Secure Socket Layer的缩写

TLS与SSL对于不是专业搞安全的开发人员来讲,可以认为是差不多的,这二者是并列关系,详细差异见 http://kb.cnblogs.com/page/197396/

KEY 通常指私钥。

CSR 是Certificate Signing Request的缩写,即证书签名请求,这不是证书,可以简单理解成公钥,生成证书时要把这个提交给权威的证书颁发机构。

CRT 即 certificate的缩写,即证书。

X.509 是一种证书格式.对X.509证书来说,认证者总是CA或由CA指定的人,一份X.509证书是一些标准字段的集合,这些字段包含有关用户或设备及其相应公钥的信息. X.509证书文件一般以.crt结尾,根据该文件的内容编码格式,可以分为以下二种格式:

PEM - Privacy Enhanced Mail,打开看文本格式,以"-----BEGIN..."开头, "-----END..."结尾,内容是BASE64编码.
Apache和*NIX服务器偏向于使用这种编码格式.

DER - Distinguished Encoding Rules,打开看是二进制格式,不可读.
Java和Windows服务器偏向于使用这种编码格式

OpenSSL 相当于SSL的一个实现,如果把SSL规范看成OO中的接口,那么OpenSSL则认为是接口的实现。接口规范本身是安全没问题的,但是具体实现可能会有不完善的地方,比如之前的"心脏出血"漏洞.

证书颁发的基本流程,首先证书应该是由机构来颁发的,即 Certificate Agent,公认的CA机构颁发证书具有公信力,浏览器获取到证书的颁发机构信息就可以知道网站是经过公认证书机构认证的,是可信的,地址栏通常会显示绿色认证标记。这些CA颁发的证书是要收费的,作为开发测试,或者一些不是很重要的场合,这显然不划算,那么就可以通过 openssl 给自己颁发证书。步骤如下,为了方便管理,先建一个cert目录,cd到该目录,以下所有命令的当前路径均为该目录:

  1. 生成私钥KEY,这一步执行完以后,cert目录下会生成server.key文件

    openssl genrsa -des3 -out server.key 2048

  2. 生成证书请求文件CSR,该命令先进入交互模式,让你填一堆东西

    openssl req -new -key server.key -out server.csr

要注意的是Common Name这里,要填写成使用SSL证书的域名或主机名,否则浏览器不能确认证书与网站的关系。例如https://www.domain.com/xxx 就填 www.domain.com

  1. 生成CA的证书

前面提过X.509证书的认证者总是CA或由CA指定的人,所以得先生成一个CA的证书

openssl req -new -x509 -key server.key -out ca.crt -days 3650
  1. 最后用第3步的CA证书给自己颁发一个证书玩玩

    openssl x509 -req -days 3650 -in server.csr -CA ca.crt -CAkey server.key -CAcreateserial -out server.crt

执行完以后,cert目录下server.crt 就是我们需要的证书。

扩展Fiddler功能

Fildder 的扩展主要方式是通过重写 Fiddler 规则脚本, 或编写 Fiddler 插件实现特定功能. Fiddler是支持多种脚本编程的, 主要是 JScript.Net 和 C#, Fiddler 安装目录下有规则文件模板 SampleRules, 有 JScript.Net 和 C# 版本. 通过菜单 Rules => Customize Rule ... 打开脚本编辑器,如果初次使用会提示安装脚本工具。这个脚本是fiddler在启动时加载的脚本,所有监听到的数据也都会流经这个脚本进行处理. FiddlerScript Editor 是自带脚本编辑插件, 热键 Ctrl+R 激活,新版本默认是自带的,旧版本可自行安装。具体参考官方文档JScript.NET Reference, FiddlerScript Reference, Extend Fiddler

编写Fiddler插件需要安装的开发环境:

  • .net framework ◦本文安装使用的是.net framework v4.5.2
  • visual studio fiddler官方推荐visual studio 2010以上版本

.net reflector反编译软件反编译fiddler自带的插件可以帮助理解插件工作原理,例如,在fiddler中查看Inspectors对应的插件. 选中Inspectors中任意一个tab,然后右键点击 inspector properties,查看inspector对应的插件。


.Net Reflector 9.0

编写代码之前, 先来了解一下 Fiddler 对象模型结构, 如果使用 Fiddler ScriptEditor, 所有这些对象信息可以在 View => Class Explore 打开. 先来了解 FiddlerObject, 这是基础服务类, 它包含了像日志记录, 状态信息修改等:

FiddlerObject 基础类对象
    +--FileExtension:   System.String
    +--Language:        Fiddler.ScriptLanguage
    +--StatusText:      System.String 修改状态栏信息
    +--UI:              Fiddler.frmViewer
    +--alert(sMesssage) 弹框提示
    +--createDictionary()
    +--flashWindow()
    +--log(sMessage)    记录日志
    +--playSound(sSoundname)
    +--prompt(sMessage)
    +--prompt(sMessage, sDefaultValue)
    +--prompt(sMessage, sDefaultValue, sWindowTitle)
    +--ReloadScript()   重新加载规则脚本
    +--uiInvoke(oMI)
    +--uiInvokeAsync(oMI, args)
    +--utilIssueRequest(sRequest)
    +--WatchPreference(sPref, oFN)

FiddlerApplication 当前运行的应用程序对象
    +--

FiddlerApplication.UI 当前运行的应用程序UI对象
    +--

FiddlerApplication.oProxy 当前运行的应用程序UI对象
    +--

CONFIG 配置类对象用来读取Fiddler配置
    +--

Utilities 工具类对象
    +--

Session
    +--host     包含端口的主机名
    +--hostname 主机名
    +--port     主机端口

HTTPRequestHeaders
    +--

HTTPResponseHeaders
    +--

WebSocketMessage
    +--

自动镜像资源文件

现在我需要改写规则脚本, 让它来为我做点事, 当我运行小程序时, 如果有大量的资源请求, 我希望通过规则脚本来实现资源文件的自动镜像功能. 一下是改写后的规则脚步输出的日志, 它记录着每一个被镜像的资源文件, 如果要手工去做这样的事, 我想是不太现实的:

11:40:44:8230 【M】...\Mapping\lihe-1.oss-cn-hangzhou.aliyuncs.com\gift\...jpg
11:40:44:8260 【M】...\Mapping\lihe-1.oss-cn-hangzhou.aliyuncs.com\gift\...jpg
11:40:44:8700 【M】...\Mapping\lihe-1.oss-cn-hangzhou.aliyuncs.com\gift\...jpg
11:40:44:8740 【M】...\Mapping\lihe-1.oss-cn-hangzhou.aliyuncs.com\gift\...jpg
11:40:44:8880 【M】...\Mapping\lihe-1.oss-cn-hangzhou.aliyuncs.com\gift\...jpg
11:40:44:9240 【M】...\Mapping\lihe-1.oss-cn-hangzhou.aliyuncs.com\gift\...png
11:40:44:9780 【M】...\Mapping\lihe-1.oss-cn-hangzhou.aliyuncs.com\gift\...png
11:40:45:0010 【M】...\Mapping\lihe-1.oss-cn-hangzhou.aliyuncs.com\gift\...png
11:40:45:0040 【M】...\Mapping\lihe-1.oss-cn-hangzhou.aliyuncs.com\gift\...png
11:40:45:0090 【M】...\Mapping\lihe-1.oss-cn-hangzhou.aliyuncs.com\gift\...png
11:40:45:0190 【M】...\Mapping\lihe-1.oss-cn-hangzhou.aliyuncs.com\gift\...png

脚步代码如下, 通过 RulesOption 给 Rules 菜单添加了一个 Mapping Content 子菜单, 默认为勾选状态. 一打开捕捉功能 就会开始做资源镜像. 定义了 buildPath 方法来建立嵌套的子目录. 重写了 OnDone 事件, 这个事件会在 Session 得到响应后发生, 这时合适将 ResponseBody 的数据保存到文件里. 将一下代码复制粘贴到 class Handlers 开始的位置, 保存就可以运行, 这种通过改写规则的功能性扩展来得更便利, 比编写插件更快.

public static RulesOption("&Mapping Content")
var m_Mapping: boolean = true;
static function buildPath(fso, root, subs){
    if( !fso.FolderExists(root) ){
        FiddlerObject.log("Build Path: "+root);
        fso.CreateFolder(root);
    }
    if( subs.length ) buildPath( fso, root+subs.shift()+"\\", subs);
}
static function OnDone(oSession: Session) {
    if(!m_Mapping){
        FiddlerObject.StatusText = "Check [Rules=>Mapping Content] to save resources";
        return;
    }
    var rep = new RegExp(".+"+oSession.host,"ig");
    var ROOT = "C:\\Users\\Administrator\\Desktop\\Mapping\\";
    var path = oSession.fullUrl.Replace(rep.exec(oSession.fullUrl)[0],"")
        .replace(/[:\|\*]/g,"-").replace(/[\\\/]/g,"\\"); // NOTE: diff between Replace & replace
    var q = path.IndexOf("?");
    var s = path.IndexOf("#");
    if(q>0){
        path = path.Remove(q);
    }else if(s>0){
        path = path.Remove(s);
    }
    if( !path.length ) path = "index.dat";
    var isFileName = /\.\w+$/.test(path);
    path = (isFileName? path.replace("\\",""):path.replace(/[\/|\\]/g, "_").replace("_","")+".raw");
    var fileName = path.replace(/.+\\/,"");
    var folder = oSession.hostname + "\\" + path.replace(/[^\\]+$/,"");
    if(fileName.length>192) fileName = fileName.substring(fileName.length-192);
    var fso = new ActiveXObject("Scripting.FileSystemObject");
    if( m_DisableCaching && fso.FileExists(ROOT + folder + fileName)) return;
    FiddlerObject.log("【M】" + ROOT + folder + fileName);
    
    try
    {
        buildPath( fso, ROOT, folder.split("\\") );
        if( !fso.FileExists(ROOT+"list.log") ){
            var log = fso.CreateTextFile(ROOT+"list.log");
        }
        var ForReading = 1, ForWriting = 2, ForAppending = 8;
        var TristateUseDefault = -2, TristateTrue = -1, TristateFalse = 0;
        var f = fso.GetFile(ROOT+"list.log");
        var log = f.OpenAsTextStream(ForAppending, TristateUseDefault);
        log.WriteLine(folder+fileName);
        log.Close();

        oSession.SaveResponseBody(ROOT + folder + fileName);
        /*
        var fdr = fso.GetFolder(ROOT + folder);
        var f = fso.CreateTextFile(ROOT + folder + fileName, true);
        f.Write(oSession.ResponseBody); // CTL_E_ILLEGALFUNCTIONCALL
        f.Write(Utilities.ByteArrayToString(oSession.responseBodyBytes)); //???
        f.Close();
        */
    }
    catch (e)
    {
        FiddlerObject.log (e);
    }
}

以上脚本正常运行需要目录的读写权限, 否则 Fiddler 会出现类似一下的提示:

10:39:43:3270 【M】C:\Users\Administrator\Desktop\Mapping\www.gmail.com\index.dat
10:39:43:3280 Error: 异常来自 HRESULT:0x800A0046 (CTL_E_PERMISSIONDENIED)

另外, 这段代码细节处理还不够, 经常会因为文件路径问题弹框, 不过这已经够我用了, 以后有时间再写一个Fiddler插件.

微信扫一扫打赏坚果
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,324评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,303评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,192评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,555评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,569评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,566评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,927评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,583评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,827评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,590评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,669评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,365评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,941评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,928评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,159评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,880评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,399评论 2 342

推荐阅读更多精彩内容