Fiddler是个很不错的工具,用来调试分析WEB页面与服务接口相当给力;做好代理,用来处理手机应用的WEB调试分析也相当好使;写好脚本则更能够帮你抓取数据到文件、数据库,部分实现自动化,甚至远超一些同类专业产品。
Fiddler的界面
常规功能- 可以用来指定抓取所有的WEB通讯,也可以只抓取指定进程的通讯。
File-Capture Traffic ; Any Process 或拖动选定进程窗口
2.可以用来查看一个URL打开后,浏览器与后端的交互
3.可以查看任意一个HTTP交互,看请求和响应的原始报文,帮助你了解HTTP协议
看原始报文
4.可以设置丰富的过滤条件,确保聚焦
过滤条件
5.可以以各种形态查看数据,并提供了工具来做转换【这个比较丰富,但隐藏较深】
隐藏较深的文本转换工具
6.可以编写脚本,实现各个阶段的处理
入口在这里,可以基于类似Windows下的WScript,甚至使用一些ActiveX组件实现并发机制、通讯与数据存储。
脚本入口
- OnBeforeRequest 在请求发生前调用
- OnPeekAtResponseHeaders 在头到达后调用
- OnBeforeResponse 在内容到达后,还没有处理前调用
import System;
import System.Windows.Forms;
import Fiddler;
// INTRODUCTION
//
// Well, hello there!
//
// Don't be scared! :-)
//
// This is the FiddlerScript Rules file, which creates some of the menu commands and
// other features of Fiddler. You can edit this file to modify or add new commands.
//
// The original version of this file is named SampleRules.js and it is in the
// Program FilesFiddler folder. When Fiddler first runs, it creates a copy named
// CustomRules.js inside your DocumentsFiddler2Scripts folder. If you make a
// mistake in editing this file, simply delete the CustomRules.js file and restart
// Fiddler. A fresh copy of the default rules will be created from the original
// sample rules file.
// The best way to edit this file is to install the FiddlerScript Editor, part of
// the free SyntaxEditing addons. Get it here: http://fiddler2.com/r/?SYNTAXVIEWINSTALL
// GLOBALIZATION NOTE: Save this file using UTF-8 Encoding.
// JScript.NET Reference
// http://fiddler2.com/r/?msdnjsnet
//
// FiddlerScript Reference
// http://fiddler2.com/r/?fiddlerscriptcookbook
class Handlers
{
// *****************
//
// This is the Handlers class. Pretty much everything you ever add to FiddlerScript
// belongs right inside here, or inside one of the already-existing functions below.
//
// *****************
// The following snippet demonstrates a custom-bound column for the Web Sessions list.
// See http://fiddler2.com/r/?fiddlercolumns for more info
// The following snippet demonstrates how to create a custom tab that shows simple text
//
// If a given session has response streaming enabled, then the OnBeforeResponse function
// is actually called AFTER the response was returned to the client.
//
// In contrast, this OnPeekAtResponseHeaders function is called before the response headers are
// sent to the client (and before the body is read from the server). Hence this is an opportune time
// to disable streaming (oSession.bBufferResponse = true) if there is something in the response headers
// which suggests that tampering with the response body is necessary.
//
// Note: oSession.responseBodyBytes is not available within this function!
//
static function OnPeekAtResponseHeaders(oSession: Session) {
//FiddlerApplication.Log.LogFormat("Session {0}: Response header peek shows status is {1}", oSession.id, oSession.responseCode);
if (m_DisableCaching) {
oSession.oResponse.headers.Remove("Expires");
oSession.oResponse["Cache-Control"] = "no-cache";
}
if ((bpStatus>0) && (oSession.responseCode == bpStatus)) {
oSession["x-breakresponse"]="status";
oSession.bBufferResponse = true;
}
if ((null!=bpResponseURI) && oSession.uriContains(bpResponseURI)) {
oSession["x-breakresponse"]="uri";
oSession.bBufferResponse = true;
}
}
static function FileExsitInDirectory(fso:Object, filename:String , dirpath:String )
{
var curPath = dirpath + "/" + filename ;
var objset , objFolders , FolderName, ret;
if (fso.FileExists(curPath))
{
return curPath;
}
else
{
var objset = fso.getFolder(dirpath);
var objFolders = objset.SubFolders;
var fenum = new Enumerator(objset.SubFolders);
for (var i = 0 ; !fenum.atEnd(); fenum.moveNext(),i++)
{
var FolderName = dirpath + "/" + fenum.item().Name + "/";
var ret = FileExsitInDirectory(fso, filename, FolderName);
if( ret != "NULL" )
{
return ret
}
}
return "NULL";
}
}
static function OnBeforeResponse(oSession: Session)
{
if (m_Hide304s && oSession.responseCode == 304)
{
oSession["ui-hide"] = "true";
}
//如果来自指定网站,且是jpg,则写文件 image/jpeg
if(
(oSession.RequestHeaders.AllValues("Host").Contains(".nvshens.org") ||
oSession.RequestHeaders.AllValues("Host").Contains(".onvshen.com") ||
oSession.RequestHeaders.AllValues("Host").Contains(".umei.cc") ||
oSession.RequestHeaders.AllValues("Host").Contains(".ffyinxiang.com") ||
oSession.RequestHeaders.AllValues("Host").Contains(".26abc.com")||true)
&&
oSession.ResponseHeaders.AllValues("Content-Type").Contains("image/jpeg") )
{
var whindex = oSession.url.IndexOf ('?');
if (whindex <= 0)
whindex = oSession.url.Length;
var file_url = oSession.url.Substring (0,whindex);
FiddlerObject.log (file_url);
whindex = oSession.url.IndexOf ('.jpg');
if ((whindex > 0) && (oSession.GetResponseBodyAsString().Length > 100000))
{
whindex = whindex+4;
FiddlerObject.log (file_url);
file_url = file_url.Substring (0,whindex).Replace ('/','_').Replace('%','B').Replace('?','7').Replace('&','-').Replace(':','_');
FiddlerObject.log ("=============="+file_url);
var file_path = "d:/PRVIT/jpg/"+file_url;
try
{
var fso = new ActiveXObject("Scripting.FileSystemObject");
var retval = FileExsitInDirectory(fso,file_url,"d:/PRVIT/jpg/");
FiddlerObject.log (retval);
if ("NULL" == retval)
{
var stream = new ActiveXObject('Adodb.Stream');
stream.Mode = 3;
stream.Open();
stream.Type = 1;
//stream.Charset = 'unicode';
//stream.WriteText(s);
stream.Position = 0;
stream.Type = 1;
//stream.Position = 2;
//var bs = stream.Read();
//stream.Position = 0;
stream.Write(oSession.responseBodyBytes);
//stream.SetEOS();
stream.SaveToFile(file_path,1);
stream.Close();
oSession["ui-backcolor"] = "yellow";
}
else
{
oSession["ui-strikeout"] = "true";
oSession["ui-backcolor"] = "green";
}
}
catch(err)
{
FiddlerObject.log (err.message);
oSession["ui-backcolor"] = "red";
}
}
else
{
oSession["ui-color"] = "red";
}
}
}
// The Main() function runs everytime your FiddlerScript compiles
static function Main() {
var today: Date = new Date();
FiddlerObject.StatusText = " CustomRules.js was loaded at: " + today;
// Uncomment to add a "Server" column containing the response "Server" header, if present
// UI.lvSessions.AddBoundColumn("Server", 50, "@response.server");
// Uncomment to add a global hotkey (Win+G) that invokes the ExecAction method below...
// UI.RegisterCustomHotkey(HotkeyModifiers.Windows, Keys.G, "screenshot");
}
// These static variables are used for simple breakpointing & other QuickExec rules
BindPref("fiddlerscript.ephemeral.bpRequestURI")
public static var bpRequestURI:String = null;
BindPref("fiddlerscript.ephemeral.bpResponseURI")
public static var bpResponseURI:String = null;
BindPref("fiddlerscript.ephemeral.bpMethod")
public static var bpMethod: String = null;
static var bpStatus:int = -1;
static var uiBoldURI: String = null;
static var gs_ReplaceToken: String = null;
static var gs_ReplaceTokenWith: String = null;
static var gs_OverridenHost: String = null;
static var gs_OverrideHostWith: String = null;
// The OnExecAction function is called by either the QuickExec box in the Fiddler window,
// or by the ExecAction.exe command line utility.
static function OnExecAction(sParams: String[]): Boolean {
FiddlerObject.StatusText = "ExecAction: " + sParams[0];
var sAction = sParams[0].toLowerCase();
switch (sAction) {
case "bold":
if (sParams.Length<2) {uiBoldURI=null; FiddlerObject.StatusText="Bolding cleared"; return false;}
uiBoldURI = sParams[1]; FiddlerObject.StatusText="Bolding requests for " + uiBoldURI;
return true;
case "bp":
FiddlerObject.alert("bpu = breakpoint request for urinbpm = breakpoint request methodnbps=breakpoint response statusnbpafter = breakpoint response for URI");
return true;
case "bps":
if (sParams.Length<2) {bpStatus=-1; FiddlerObject.StatusText="Response Status breakpoint cleared"; return false;}
bpStatus = parseInt(sParams[1]); FiddlerObject.StatusText="Response status breakpoint for " + sParams[1];
return true;
case "bpv":
case "bpm":
if (sParams.Length<2) {bpMethod=null; FiddlerObject.StatusText="Request Method breakpoint cleared"; return false;}
bpMethod = sParams[1].toUpperCase(); FiddlerObject.StatusText="Request Method breakpoint for " + bpMethod;
return true;
case "bpu":
if (sParams.Length<2) {bpRequestURI=null; FiddlerObject.StatusText="RequestURI breakpoint cleared"; return false;}
bpRequestURI = sParams[1];
FiddlerObject.StatusText="RequestURI breakpoint for "+sParams[1];
return true;
case "bpa":
case "bpafter":
if (sParams.Length<2) {bpResponseURI=null; FiddlerObject.StatusText="ResponseURI breakpoint cleared"; return false;}
bpResponseURI = sParams[1];
FiddlerObject.StatusText="ResponseURI breakpoint for "+sParams[1];
return true;
case "overridehost":
if (sParams.Length<3) {gs_OverridenHost=null; FiddlerObject.StatusText="Host Override cleared"; return false;}
gs_OverridenHost = sParams[1].toLowerCase();
gs_OverrideHostWith = sParams[2];
FiddlerObject.StatusText="Connecting to [" + gs_OverrideHostWith + "] for requests to [" + gs_OverridenHost + "]";
return true;
case "urlreplace":
if (sParams.Length<3) {gs_ReplaceToken=null; FiddlerObject.StatusText="URL Replacement cleared"; return false;}
gs_ReplaceToken = sParams[1];
gs_ReplaceTokenWith = sParams[2].Replace(" ", "%20"); // Simple helper
FiddlerObject.StatusText="Replacing [" + gs_ReplaceToken + "] in URIs with [" + gs_ReplaceTokenWith + "]";
return true;
case "allbut":
case "keeponly":
if (sParams.Length<2) { FiddlerObject.StatusText="Please specify Content-Type to retain during wipe."; return false;}
UI.actSelectSessionsWithResponseHeaderValue("Content-Type", sParams[1]);
UI.actRemoveUnselectedSessions();
UI.lvSessions.SelectedItems.Clear();
FiddlerObject.StatusText="Removed all but Content-Type: " + sParams[1];
return true;
case "stop":
UI.actDetachProxy();
return true;
case "start":
UI.actAttachProxy();
return true;
case "cls":
case "clear":
UI.actRemoveAllSessions();
return true;
case "g":
case "go":
UI.actResumeAllSessions();
return true;
case "goto":
if (sParams.Length != 2) return false;
Utilities.LaunchHyperlink("http://www.google.com/search?hl=en&btnI=I%27m+Feeling+Lucky&q=" + Utilities.UrlEncode(sParams[1]));
return true;
case "help":
Utilities.LaunchHyperlink("http://fiddler2.com/r/?quickexec");
return true;
case "hide":
UI.actMinimizeToTray();
return true;
case "log":
FiddlerApplication.Log.LogString((sParams.Length<2) ? "User couldn't think of anything to say..." : sParams[1]);
return true;
case "nuke":
UI.actClearWinINETCache();
UI.actClearWinINETCookies();
return true;
case "screenshot":
UI.actCaptureScreenshot(false);
return true;
case "show":
UI.actRestoreWindow();
return true;
case "tail":
if (sParams.Length<2) { FiddlerObject.StatusText="Please specify # of sessions to trim the session list to."; return false;}
UI.TrimSessionList(int.Parse(sParams[1]));
return true;
case "quit":
UI.actExit();
return true;
case "dump":
UI.actSelectAll();
UI.actSaveSessionsToZip(CONFIG.GetPath("Captures") + "dump.saz");
UI.actRemoveAllSessions();
FiddlerObject.StatusText = "Dumped all sessions to " + CONFIG.GetPath("Captures") + "dump.saz";
return true;
default:
if (sAction.StartsWith("http") || sAction.StartsWith("www.")) {
System.Diagnostics.Process.Start(sParams[0]);
return true;
}
else
{
FiddlerObject.StatusText = "Requested ExecAction: '" + sAction + "' not found. Type HELP to learn more.";
return false;
}
}
}
}
自动化
- 抓取图片并提出重复的
static function FileExsitInDirectory(fso:Object, filename:String , dirpath:String )
{
var curPath = dirpath + "/" + filename ;
var objset , objFolders , FolderName, ret;
if (fso.FileExists(curPath))
{
return curPath;
}
else
{
var objset = fso.getFolder(dirpath);
var objFolders = objset.SubFolders;
var fenum = new Enumerator(objset.SubFolders);
for (var i = 0 ; !fenum.atEnd(); fenum.moveNext(),i++)
{
var FolderName = dirpath + "/" + fenum.item().Name + "/";
var ret = FileExsitInDirectory(fso, filename, FolderName);
if( ret != "NULL" )
{
return ret
}
}
return "NULL";
}
}
static function OnBeforeResponse(oSession: Session)
{
if (m_Hide304s && oSession.responseCode == 304)
{
oSession["ui-hide"] = "true";
}
//如果来自指定网站,且是jpg,则写文件 image/jpeg
if(
(oSession.RequestHeaders.AllValues("Host").Contains(".mm115.net") ||
oSession.RequestHeaders.AllValues("Host").Contains(".jzsjwk.com"))
&&
oSession.ResponseHeaders.AllValues("Content-Type").Contains("image/jpeg") )
{
var whindex = oSession.url.IndexOf ('?');
if (whindex <= 0)
whindex = oSession.url.Length;
var file_url = oSession.url.Substring (0,whindex);
whindex = oSession.url.IndexOf ('.jpg');
if ((whindex > 0) && (oSession.GetResponseBodyAsString().Length > 40000))
{
whindex = whindex+4;
file_url = file_url.Substring (0,whindex).Replace ('/','_').Replace('%','B').Replace('?','7').Replace('&','-').Replace('img22.jzsjwk.com','img1.mm115.net');
var file_path = "d:/PRVIT/jpg/"+file_url;
try
{
var fso = new ActiveXObject("Scripting.FileSystemObject");
var retval = FileExsitInDirectory(fso,file_url,"d:/PRVIT/jpg/");
FiddlerObject.log (retval);
if ("NULL" == retval)
{
var stream = new ActiveXObject('Adodb.Stream');
stream.Mode = 3;
stream.Open();
stream.Type = 1;
//stream.Charset = 'unicode';
//stream.WriteText(s);
stream.Position = 0;
stream.Type = 1;
//stream.Position = 2;
//var bs = stream.Read();
//stream.Position = 0;
stream.Write(oSession.responseBodyBytes);
//stream.SetEOS();
stream.SaveToFile(file_path,1);
stream.Close();
oSession["ui-backcolor"] = "yellow";
}
else
{
oSession["ui-strikeout"] = "true";
oSession["ui-backcolor"] = "green";
}
}
catch(err)
{
FiddlerObject.log (err.message);
oSession["ui-backcolor"] = "red";
}
}
else
{
oSession["ui-color"] = "red";
}
}
}
- 抓取内容,并存放到数据库
var sql = "";
try
{
var con =new ActiveXObject("ADODB.Connection");
//con.Provider="Microsoft.ACE.OLEDB.18.0";
var rs=new ActiveXObject("ADODB.Recordset");
//var access_db_path = "d:/fiddler_web_service_analysis.accdb" ;
//con.ConnectionString="Data Source="+access_db_path;
//ODBC DSN name ,config by windows odbc
con.open("DSN=db_hsb_vs_ahs;") ;
//FiddlerObject.alert(1);
sql = "insert into t_call_record (call_timestamp,request_send_timestamp,response_recv_timestamp,sitename,url,request,response,spend_second,content_type,content_length) values(" +
strVar1(oSession.Timers.FiddlerBeginRequest) + "," +
strVar1(oSession.Timers.ClientDoneRequest) + "," +
strVar1(oSession.Timers.ServerDoneResponse) + "," +
strVar1(oSession.RequestHeaders.AllValues("Host")) + "," +
strVar1(oSession.url.Substring (0,whindex)) + "," +
strVar1(oSession.RequestHeaders.ToString ()+oSession.GetRequestBodyAsString()) + "," +
strVar1(oSession.ResponseHeaders.ToString ()+oSession.GetResponseBodyAsString()) + "," +
etimes*1000 + "," +
strVar1(oSession.ResponseHeaders.AllValues("Content-Type")) +"," +
oSession.ResponseHeaders.AllValues("Content-Length")+0
+");";
//FiddlerObject.alert(sql);
rs.open(sql,con);
oSession["ui-color"] = "red";
//rs.close();
// rs=NULL;
con.close();
// con = NULL;
}
catch(exp)
{
var txt="Error description: " + exp.message + "nn" + sql;
FiddlerObject.log(txt);
oSession["ui-strikeout"] = "true";
}
调试手机上的应用
打开对HTTPS的捕获与分析
启动代理
查看代理IP地址
在客户端上信任根证书
手机上还要再wifi哪里设置好此代理。如此即可抓取手机的报文了。
暑期编程PK赛 得CSDN机械键盘等精美礼品!


