- PVSM.RU - https://www.pvsm.ru -

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

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

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

FiddlerScript

FiddlerScript [5] — это встроенный в 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.

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

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];
	}
}

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

Код полностью [10]

Написание .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;
}

Полный код [11]

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

Вот так мы научились писать расширения для Fiddler.

Автор: tangro

Источник [12]


Сайт-источник PVSM.RU: https://www.pvsm.ru

Путь до страницы источника: https://www.pvsm.ru/net/83948

Ссылки в тексте:

[1] неоднократно: http://habrahabr.ru/company/infopulse/blog/156711/

[2] рассказывали: http://habrahabr.ru/post/140147/

[3] Fiddler: http://www.telerik.com/fiddler

[4] прошлой статье: http://habrahabr.ru/company/infopulse/blog/251259/

[5] FiddlerScript: http://docs.telerik.com/fiddler/KnowledgeBase/FiddlerScript/ModifyRequestOrResponse

[6] Хорошая вводная статья о FiddlerScript: http://blogs.telerik.com/fiddler/posts/13-07-15/understanding-fiddlerscript

[7] FiddlerScript Editor: http://www.telerik.com/download/fiddler/fiddlerscript-editor

[8] исходные данные: https://github.com/ezhikus/HabraImagesFixer/blob/master/img_info/fixable_images.txt

[9] статьи с битой ссылкой на картинку: http://geektimes.ru/post/110/

[10] Код полностью: https://github.com/ezhikus/HabraImagesFixer/blob/master/FiddlerScriptBasedExtension/CustomRules.js

[11] Полный код: https://github.com/ezhikus/HabraImagesFixer/tree/master/DotNetBasedExtension

[12] Источник: http://habrahabr.ru/post/251363/