Модификация HTTP-трафика с помощью FiddlerScript и .NET-плагинов к Fiddler

  • Tutorial
На Хабре уже неоднократно рассказывали о таком мощном и удобном средстве мониторинга HTTP-трафика, как Fiddler. Все имеющиеся статьи, однако, рассказывают о встроенных фичах программы, не акцентируя внимания на возможностях её расширения, которых существует целых две: с помощью встроенного языка FiddlerScript и с помощью написания .NET-плагинов. В этой статье мы рассмотрим и то, и другое, а чтобы было интереснее — используем их для решения вполне практической задачи, о которой я писал в своей прошлой статье (подмене битых ссылок на картинки в статьях на Хабре на рабочие).

Итак, давайте вспомним для начала, чем закончилась прошлая статья: мы получили список нерабочих ссылок на картинки и соответствующих им рабочих ссылок на веб-архиве. Теперь нужно отдать их браузеру и для этого мы напишем расширения к Fiddler (одно на FiddlerScript и одно на .NET). Обратите внимание на удобства полученного решения: да, нам нужно будет запустить Fiddler, но зато битые ссылки будут подменяться на рабочие независимо от домена статьи (хабр, гиктаймс или мегамозг), независимо от используемого браузера (лишь бы имел поддержку прокси) и даже мобильные устройства можно будет настроить на использование установленного на компьютере Fiddler в качестве прокси.

FiddlerScript


FiddlerScript — это встроенный в Fiddler язык программирования, основанный на JScript.NET, позволяющий анализировать и изменять входящий и исходящий траффик, расширять функциональность самого Fiddler, модифицировать его интерфейс.
Пара ссылок по теме:


Писать код нужно в файл, который открывается по клику в меню на Rules->Customize Rules. Если вдруг запорете его — просто удалите, Fiddler пересоздаст его из резервной копии.

Простейшая подмена одной ссылки на другую на FiddlerScript будет выглядеть как добавление в обработчик OnBeforeRequest вот такого кода:

static function OnBeforeRequest(oSession: Session) {
...
if (oSession.url=="www.example.com/bad_url.jpg") {
      oSession.url = "www.example.com/good_url.jpg";
    }
}


Нам нужно подменить 13863 ссылки. Писать такое лес «ифов» — малопродуктивно. Вспомним, что FiddlerScript основан на JScript.NET, JScript.NET — это .NET, а в .NET есть весьма производительные структуры данных для хранения набора строк и быстрого поиска по нему, в основе которого лежат хеш-таблицы. Да-да, я о StringDictionary.

Возьмём наши исходные данные и парой нехитрых операций по автозамене в любом текстовом редакторе с поддержкой регулярных выражений приведём его к виду:

myDict.Add("img224.imageshack.us/img224/410/yandexmoney7mg.gif", "web.archive.org/web/20060723135036/http://img224.imageshack.us:80/img224/410/yandexmoney7mg.gif");
myDict.Add("blaugh.com/wp-content/themes/blaugh/images/cartoon-gd_01.gif", "web.archive.org/web/20070703010741/http://blaugh.com/wp-content/themes/blaugh/images/cartoon-gd_01.gif");
myDict.Add("blaugh.com/cartoons/060712_google_life.gif", "web.archive.org/web/20120112151300/http://blaugh.com/cartoons/060712_google_life.gif");
...


Инициализировать словарь нужнов всего однажды (например, в обработчике OnBoot, а использовать при поиске его мы можем в каждом вызове OnBeforeRequest:

static var myDict: StringDictionary = null;

static function OnBoot() {
	myDict = new StringDictionary();
	myDict.Add("img224.imageshack.us/img224/410/yandexmoney7mg.gif", "web.archive.org/web/20060723135036/http://img224.imageshack.us:80/img224/410/yandexmoney7mg.gif");
	myDict.Add("blaugh.com/wp-content/themes/blaugh/images/cartoon-gd_01.gif", "http://web.archive.org/web/20070703010741/http://blaugh.com/wp-content/themes/blaugh/images/cartoon-gd_01.gif");
	myDict.Add("blaugh.com/cartoons/060712_google_life.gif", "http://web.archive.org/web/20120112151300/http://blaugh.com/cartoons/060712_google_life.gif");
	....
    }

...

static function OnBeforeRequest(oSession: Session) {
...
	if (null != myDict && myDict.ContainsKey(oSession.url)) {
	    oSession.url = myDict[oSession.url];
	}
}


Сохраняем, проверяем открытием статьи с битой ссылкой на картинку, видим картинку, которая без этой подмены была недоступна — ура, всё работает!

Код полностью

Написание .NET-плагина к Fiddler


Если вам не сильно понравилось писать код на странном языке JScript.NET в странном редакторе и запускать его странным способом копипасты в конфиг-файл, ожидая при этом по 30 сек, пока распарсится и скомпилируеся написанный нами скрипт — к вашим услугам вся мощь C#, .NET, Visual Studio и прочих радостей жизни!

Коротко о создании проекта:
1. Запускаем Visual Studio, создаём новый .NET-проект типа «Библиотека классов».
2. Если пишете под Fiddler 4 — выбирайте в свойствах проекта .NET версии 4, если под Fiddler 2 — .NET версии 3.5
3. Добавляйте в зависимости сам Fiddler (экзешник Fiddler.exe, лежащий в своей папке в Program Files).
4. В коде нужно указать, какую минимальную версию Fiddler вы поддерживаете:
using Fiddler;

// Extension requires Fiddler 2.2.8.6+ because it uses types introduced in v2.2.8...
[assembly: Fiddler.RequiredVersion("2.2.8.6")]

5. Вам нужно написать класс, реализовывающий интерфейс IAutoTamper. События у него, в общем-то те же, что и были в нашем коде на FiddlerScript, поэтому вот он схематически:
using System;
using Fiddler;
using System.Collections.Specialized;

[assembly: Fiddler.RequiredVersion("2.3.5.0")]

public class HabraFixer : IAutoTamper    // Ensure class is public, or Fiddler won't see it!
{
    public HabraFixer()
    {
    }

    public void OnLoad()
    {
        myDict = new StringDictionary();
        myDict.Add("img224.imageshack.us/img224/410/yandexmoney7mg.gif", "web.archive.org/web/20060723135036/http://img224.imageshack.us:80/img224/410/yandexmoney7mg.gif");
        myDict.Add("blaugh.com/wp-content/themes/blaugh/images/cartoon-gd_01.gif", "web.archive.org/web/20070703010741/http://blaugh.com/wp-content/themes/blaugh/images/cartoon-gd_01.gif");
        myDict.Add("blaugh.com/cartoons/060712_google_life.gif", "web.archive.org/web/20120112151300/http://blaugh.com/cartoons/060712_google_life.gif");
        ...
    }
    
    public void OnBeforeUnload() { }

    public void AutoTamperRequestBefore(Session oSession)
    {
        if (null != myDict && myDict.ContainsKey(oSession.url)) {
    	    oSession.url = myDict[oSession.url];
    	}
    }
    public void AutoTamperRequestAfter(Session oSession) { }
    public void AutoTamperResponseBefore(Session oSession) { }
    public void AutoTamperResponseAfter(Session oSession) { }
    public void OnBeforeReturningError(Session oSession) { }

    private StringDictionary myDict;
}


Полный код

Билдим, подкладываем сборку в %Program Files%\Fiddler2\Scripts (для всех пользователей) или в %USERPROFILE%\My Documents\Fiddler2\Scripts (только для текущего), запускаем Fiddler, проверяем — всё работает!

Вот так мы научились писать расширения для Fiddler.
  • +15
  • 11,7k
  • 3
Инфопульс Украина 223,83
Creating Value, Delivering Excellence
Поделиться публикацией
Комментарии 3
  • 0
    Спасибо за статью. Даже написав один из постов указаных у вас, никогда особо не разбирался в скриптах фидлера.
    До недавнего времени хватало функциональности доступной через GUI.
    На днях пытался обойти CORS в FF. Добавляя заголовок в ответ от сервера «Access-Control-Allow-Origin: *», но почему-то не взлетело.

    В AutoResponder есть стандартное правило *CORSPreflightAllow, добавляет нужные заголовки, но похоже затирает response body.
    Через Filter тоже не получилось организовать нормальную работу.

    Собственно вопрос к вам, вы случаем не в курсе где хранятся стандартные правила AutoResponder'а, хотелось бы посмотреть на их код и возможно отредактировать.

    Для тех кто не в курсе проблем FF с CORS
    Суть проблемы, нет возможности отключить CORS во время разработки, как это делается в хроме с --disable-web-security
    Существующий about:config -> security.fileuri.strict_origin_policy -> false это всего лишь отключение file:// URI policy

    Есть даже баг в трекере FF
    • 0
      Ну вроде там же оно, вот рассказывают детали: blog.caplin.com/2010/03/19/using-fiddler-to-help-develop-cross-domain-capable-javascript-web-applications/

      А ещё я когда-то CORS отключал написанием расширения к Firefox, там в принципе тоже пару строк всего. Правда, это давно было, может быть уже убрали такую возможность в целях безопасности, не знаю точно.
      • 0
        Да, я это пробывал, но почему-то не взлетело у меня… было не критично, поэтому не стал разбираться. Вопрос был, где находятся скрипты из стандартных правил типа *CORSPreflightAllow, заготовка открывающаяся в create custom rules их не содержит.
        По поводу расширения, сам под фф не писал, а те что решали проблему — удалили из магазина по причине безопасности. Впрочем могу ошибаться, сам я давно пересел на хром в разработке и открываю лису очень редко.

    Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

    Самое читаемое