Fiddler の Inspector プラグインを作ろう

どうもみむらです。

お仕事の関係上、アプリケーションの通信を見ることがありまして。
一般には “Burp” を使うことが多いのですが、
やっぱりサクッと見たいときには Fiddler 先生を使いたくなることがあります。[要出典]

Burp のプラグインを作る話はよくあるのですが Fiddler の話はあまりないのと、
作ってみたらサクッと出来たので記事に纏めてみようかと。


1.プロジェクトを作る

下記のようにまず、 “.NET Framework” の クラスライブラリを作成します。

Fiddler は .NET Framework の 4.6.1 を使用していますので、
バージョンは 4系を選択します。 (4.6.1 か それ以降を選択しておけば OK です)


2.Fiddler を参照に加える

Fiddler.exe を参照に加えます。

通常下記のパスに Fiddler がありますので、こちらを追加します。
%LOCALAPPDATA%\Programs\Fiddler\Fiddler.exe

また、Fiddler の Inspector プラグインはUI に Windows Forms を使用しますので System.Windows.Forms も忘れずに参照に加えます。


3.デバッグの設定をする

プラグインの開発時に F5 でデバッグ出来た方が良いですよね。

プロジェクトの設定の「デバッグ」から
Fiddler.exe (%LOCALAPPDATA%\Programs\Fiddler\Fiddler.exe) を
デバッグプログラムとして指定します。

同様に「ビルド」から、出力先のパスを
お使いのユーザのドキュメントフォルダの “Fiddler2\Inspectors” に出力するようにします。
(%USERPROFILE%\Documents\Fiddler2\Inspectors を展開したパスに保存すれば OK です)


4.Request 側と Response 側のビューのひな形を作る

それでは本題となるビューを作ってみましょう

ビューを作る際は下記のように、レスポンス用とリクエスト用を2つ定義する必要があります。

リクエスト用のビュー

基本的に Inspector2, IRequestInspector2 を継承して作ります。
上記の画像に当該するコードは下記の通りです

using Fiddler;
using System.Windows.Forms;

public class RequestView : Inspector2, IRequestInspector2
{
    /// <summary>
    /// Inspector ビューへの項目の追加やウィンドウの初期化等を行う
    /// </summary>
    /// <param name="o"></param>
    public override void AddToTab(TabPage o)
    {
        o.Text = "さんぷる!";
        o.Controls.Add(new TextBox() {Text = "リクエストヘッダ用!", Dock = DockStyle.Fill, Multiline = true, ReadOnly = true});
    }

    /// <summary>
    /// 項目が必要なくなった場合のクリーンアップ処理を書く (IDisposable の Dispose みたいな)
    /// </summary>
    public void Clear()
    {

    }

    /// <summary>
    /// POST リクエストとして送信されたメッセージ本文
    /// </summary>
    public byte[] body { get; set; }

    /// <summary>
    /// テキストが編集されたかどうかを返す
    /// </summary>
    public bool bDirty { get; }

    /// <summary>
    /// 読み取り専用項目かを取得・設定する
    /// </summary>
    public bool bReadOnly { get; set; }

    /// <summary>
    /// HTTP のリクエストヘッダ
    /// </summary>
    public HTTPRequestHeaders headers { get; set; }

    /// <summary>
    /// Inspector ビュー内の項目の順番(昇順でソートされるため、値が大きければ項目の最後に追加される)
    /// </summary>
    /// <returns>表示順番</returns>
    public override int GetOrder() => 1000;
}

レスポンス用のビュー

レスポンス用の場合は Inspector2, IResponseInspector2 を継承して作ります。
上記の画像に当該するコードは下記の通りです

using Fiddler;
using System.Windows.Forms;

public class ResponseView : Inspector2, IResponseInspector2
{
    /// <summary>
    /// Inspector ビューへの項目の追加やウィンドウの初期化等を行う
    /// </summary>
    /// <param name="o"></param>
    public override void AddToTab(TabPage o)
    {
        o.Text = "さんぷる!";
        o.Controls.Add(new TextBox()
            {Text = "レスポンスヘッダのびゅー!", Dock = DockStyle.Fill, Multiline = true, ReadOnly = true});
    }

    /// <summary>
    /// 項目が必要なくなった場合のクリーンアップ処理を書く (IDisposable の Dispose みたいな)
    /// </summary>
    public void Clear()
    {

    }

    /// <summary>
    /// 受信されたメッセージ本文
    /// </summary>
    public byte[] body { get; set; }

    /// <summary>
    /// テキストが編集されたかどうかを返す
    /// </summary>
    public bool bDirty { get; }

    /// <summary>
    /// 読み取り専用項目かを取得・設定する
    /// </summary>
    public bool bReadOnly { get; set; }

    /// <summary>
    /// HTTP のレスポンスヘッダ
    /// </summary>
    public HTTPResponseHeaders headers { get; set; }

    /// <summary>
    /// Inspector ビュー内の項目の順番(昇順でソートされるため、値が大きければ項目の最後に追加される)
    /// </summary>
    /// <returns>表示順番</returns>
    public override int GetOrder() => 1000;
}

5.Fiddler の RequiredVersion を宣言する

上記の2クラスだけではダメで、必要な Fiddler のバージョンを宣言する必要があります。

どこか1つのソースコードで問題ありませんので、
下記のようにバージョンを宣言するだけのソースコードを作成しましょう。

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

6.実行してみよう

上手くいけば下記のように、「さんぷる!」という名前の項目が追加されて
作成したプラグインが読み込まれるはずです。

画像を編集

7.目的に合わせて拡張しよう

今回の例は Inspector プラグインとして任意のビューを表示するところまでを紹介しました。
ただこれだけではBody の処理や その他のパラメータの処理がかなりおざなりになっています。

そこで下記のような、Request / Response Body のテキストを編集できるサンプルを
下記の GitHub に公開しました。
https://github.com/mimura1133/sample_fiddlerInspector

コードも極力短く、また各パラメータに関しても極力コメントを入れてありますので、
これを踏み台にして独自の Inspector プラグインを作成頂けたら幸いです。


それでは、楽しい Fiddler ライフを!

DEF CON 2019 Online Quals / Write-up

どうもみむらです。
久しぶりに wasamusume の CTF の活動を再開したくなり、リハビリがてらに参加してみました。

結果としては98位。
3人だけでひっそりと参加していたのですが、結果としてはかなり上々かも。

というわけで、解いた問題についての Write-up です。


問題のおしながき:
・welcome_to_the_game
・babytrace
・know_your_mem


welcome_to_the_game

FLAG : OOO{Game on!}
ファイルを開くと出てくる。


babytrace

FLAG : OOO{memory_objects_get_you_every_time}

claripy と angr で作られたトレーサを経由して問題のファイルを覗く問題。
プログラムは純粋に使うと2文字までしか表示されないようになっています。

eax が文字位置.

解き方

0x856 の位置に “movzx eax,[rbp+eax+buf]” という処理があり
ここで、任意の位置の文字が “eax” に積まれます。

その処理を利用して、任意の文字の位置を読んでみます。

読みたい位置を標準入力に設定(ここでは 0x25 = 最後の文字)
文字列が代入される 0x856 より先の位置まで進める。(ここでは 0x86E の puts の中で止まっている)
その状態で eax の値 (ここでは eax_63_32)を読むと、 0x7d = ‘}’ の値が取得できていることが分かる。

あとは上記を繰り返して、文字列を読んでいくとフラグが得られます。


know_your_mem

FLAG : OOO{so many bits, so many syscalls}

実行すると下記のように、シェルコードを入れるように指示されます。
ここに、文字列長とシェルコードを入力するとそれが実行されます。

シェルコードで実現する必要があることは、
プログラムのどこかに読み込まれている「フラグ」のデータを探し出して
それを読み込んで表示すること。
また、10秒間のタイムアウト値が設定されているため、それを越えての探索は出来ません。

解き方

方針1(基本的な方法)

64bit 空間のメモリを全部探すのは現実的ではないので
スタック中から何か出ていないか探します。

下記のようなアセンブラを書いて、それをシェルコードとして与えます。

bits 64

section .text
global _start

_start:
mov rsi,rsp
mov rdx,70
mov rdi,1
mov rax,1
syscall
mov rax,0
ret

どうやら白く塗ってある場所に同じ表示が出ているのでこれが使えそう。

ただ大会期間中は、メモリ位置を考慮するのが面倒くさくなったので
別の方法を使いました。


方針2(実際に試した方法)

“flag” の読み込みを r15 が指し示すメモリアドレスに読み込む処理が入っています。

shellcode 読んだ直後でも R15 が flag の入っているメモリを指し示し続けてる。
(今回はソースコードで提供されたので、コンパイラによっては別のレジスタが使われる場合もある)

というわけで下記のようなアセンブラを書いてみました。

bits 64

section .text
global _start

_start:
mov rsi,r15
mov rdx,50
mov rdi,1
mov rax,1
syscall
mov rax,r15
ret

結果としては下記の通り

というわけで r15 レジスタを参照するだけで解けました・・。
うーんこれで良いのだろうか・・。

ところで
フラグが OOO{so many bits, so many syscalls} なので
下記のようなコードを書くのが正しいのかもしれませんね・・?

余談(メモリ全探索。間に合わないけど・・。)

(ただし速度が追いつかないので改良等をする必要は大いにあります)

bits 64

section .text
global _start

_start:
mov rsi,0x100000000000

_nextpage:
add rsi,0x1000 ; mmap のアライメント.

_nextbyte:
mov rdx,10
mov rdi,1
mov rax,1 ; write は今回の seccomp の設定で許可されていたので.
syscall

_faultcheck:
cmp al,0xf2 ;EFAULT
jz _nextpage
mov eax,0x4F4F4F7B ; egg "OOO{"
inc al
scasd
jnz _nextbyte
mov rax,rdi
ret

普通に Egg Hunter の Exploit code のもじりです(苦笑)


というわけで、
久しぶりに CTF やるのと、久しぶりにアセンブラ読み書きしてるのが楽しかったので
また機会があれば CTF やりたいかもしれません。

また家にメンバーを読んでやってたのですが、
あのワイワイした感じで解くのも面白かったし。であであー。

Windows Terminal (Preview) をビルドして使おう

どうも、みむらです。

先日発表されたばかりの “Windows Terminal” を使ってみました。
とりあえず、これは今すぐ会社用PCとかにも入れておこうかと思いました。

https://twitter.com/mimura1133/status/1125824357064830979

普段使いそうなツール群を呼び出せるようにしてみたのですが、
結構使いやすそうな子のようです。

マイクロソフト社からちゃんとストア経由で今後出てくると思いますが
常に最新のものを触りたい!という人向けに、ビルド方法のメモになります。


1.ビルド環境の準備

執筆時点(2019年5月8日)では、下記のものを用意する必要があります。

1. Visual Studio 2017 (2019 だと上手くビルド出来ませんでした..)
2. Windows 10 (ストアアプリ扱いになります)

また、ビルドするためには Visual Studio 2017 にて
「C++ ユニバーサル Windows プラットフォームツール」を有効にする必要があります。


2.ビルド

下記 URL より git clone を実施してソースコードを取得します。
https://github.com/microsoft/Terminal

Clone 完了後、”git submodule” を使用して、
依存関係にあるコードもダウンロードします。

# git submodule update –init –recursive

コードの準備が完了したら “OpenConsole.sln” を Visual Studio 2017 で開きましょう。

“CascadiaPackage” を右クリック → ストア → 「アプリパッケージの作成」と選択します。

そして「サイドロード用」のパッケージとして、
お使いのアーキテクチャにチェックを入れて “Release” となっていることを確認してパッケージを作成します。

注意

ビルド中、もの凄くメモリを使います。
下手をすると下記のようなエラーが出てコンパイルエラーになることもあります。

13>c1xx : error C3859: PCH の仮想メモリを作成できませんでした
13>c1xx: note: PCH: ファイル マップ全体にメモリをコミットできません
13>c1xx: note: 詳細については https://aka.ms/pch-help をご覧ください

そのときは Visual Studio の同時コンパイル数を1にすることで
改善できる場合があります。

ツール → オプション → プロジェクトおよびソリューション → ビルド / 実行
にて「平行してビルドするプロジェクトの最大数」を1にします。


3.インストール

下記のようにビルドが完了したら、Add-AppDevPackage.ps1 を実行します。
あとはウィザードに従って進めればインストール完了となります。


なお、このファイルを常用するコンピュータに持って行き、
インストールをすることで他のコンピュータでも利用することが可能になります。

動作しないときは:

開発者モードになっているかを確認しましょう。


4.使う

早速スタートに登録されましたのでバンバン使っていきましょう。


初回起動時はこんな感じの無機質なターミナルが表示されます。

ここで Ctrl + T を押しましょう。
下図のようにいい感じにタブと設定メニューが登場します。

では右端のボタンから “Settings” を開きましょう。

下図のように json が表示されると思いますので、適宜成形 (Visual Studio であればドキュメントの整形機能があります)して眺めます。

まず、全体設定ですが確認できるのは次の通りです:

“alwaysShowTabs” はタブを画面に常時表示するかどうか。これについては “true” に書き換えておいた方が無難です。
“showTerminalTitleInTitlebar” はタイトルバーにアクティブなタブのタイトルを表示させるかどうか。
“experimental_showTabsInTitlebar” はタブをタイトルバー部分に表示するかどうか。

つぎに “profiles” の中ですが、ここに項目を追加すると呼び出せるプログラムが増えます・・!

お好きなフォントを “fontFace”, “fontSize” で設定し、
透過させたい場合は “useAcrylic” を true にした上で、 “acrylicOpacity” (1に近いほど無透過)を設定すると良いと思います。

参考までに、私の設定ファイルも置いておきます。参考までにどうぞ・・!
https://gist.github.com/mimura1133/4e65fdbf8fd686d3a3691bd9b43678ac


発表されてすぐさま使ってみて、かなり使い勝手がよさそうでしたので
私としては早く標準のコマンドプロンプトの代わりになって欲しいなと思うそんな今日この頃です。

CUI なアプリケーションを全部このタブに纏めておいたら凄く使いやすそうな感じがする。。

巻末に、私の環境でビルドしたファイル(x64 専用)もおいておきます。
どうしてもビルドに失敗してしまうかたがいれば、自己責任にてお試しください。

http://mimumimu.net/beta/programs/CascadiaPackage_1.0.0.0_Test.zip

Windows と Linux の和暦対応

どうも、みむらです。
しばらく記事を書かない間に、新暦が発表され、
そして私も会社が変わってしまいました。
 
最近はアプリ診断員にジョブチェンジしました。
IDA さんが友達です。

特に最近は iOS アプリを見ているので、
フォレンジックネタとか iOS に関するセキュリティ診断ネタであれば、
凄く話に乗れると思います。

それ以外には、Unity のアプリとか (lib2cpp の読み解きとか)
Windows ならユーザランドからカーネルランドまで。お話まってます。


閑話休題。

新暦と言えば、やはり新暦対応でしょう。
私も新暦が発表された直後から「なんとしても対応しよう」と遊んでました。

画像
(from : https://twitter.com/mimura1133/status/1112566297135480838/ )

などなど。
 
今回は、もし「令和じゃない元号にします」と発表があった際に
素早く手持ちの環境を自己責任において対応させられるように
(要出典)
Windows と Linux の対応の仕組みを見ておこう
、とそういうテーマです。

 


Windows 側での対応

Windows の場合はレジストリキーを追加します。

(注:本修正を実施した事によりご利用中のプログラムに不具合が発生しても本サイトは責任を負いかねますと共に、くれぐれもプログラムの製造元へ連絡されませんようお願い致します)

 

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Nls\Calendars\Japanese\Eras 以下に
年号情報が詰まっていますので

REG_SZ 型にて
キー名:”<開始年> <開始月> <開始日>”
値:”<フル読み>_<代表する一文字>_<英語表記>_<英語短縮表記>”

のフォーマットにてキーを生成すれば OK のようです。

 

この値を設定すると、
この値を参照しているプログラムの処理系であれば
基本的に新年号に対応出来るようになります。

画像

 


Linux (glibc) での対応

Linux の場合は locale ファイルを修正します。

(注:本修正を実施した事によりご利用中のプログラムに不具合が発生しても本サイトは責任を負いかねますと共に、くれぐれもプログラムの製造元へ連絡されませんようお願い致します)
 

locales ファイルは下記のパスに保存されています。
(Arch Linux, CentOS 7 にて確認)

/usr/share/i18n/locales/ja_JP

 
修正するのは、”era” の部分。

「○○元年」(+1 で始まるレコード)と「○○年」(+2 で始まるレコード)
を用いて年号の変換を行います。

そして年号は UTF-16BE の順番で書いていきます。

リトルエンディアンでの「令和」のバイト列

できあがった例は次の通り

新しい年号に対応させた ja_JP ファイル.

1つめの “+:1:2019//05//01:2019//12//31:<U4EE4><U548C>:%EC<U5143><U5E74> は
2019年5月1日~2019年12月31日までを「令和(<4EE4><548C>) 元年(<5143><5E74>)」

表記するというもの。

2つめの “+:1:2020//01//01:+*:<U4EE4><U548C>:%EC%Ey<U5E74> は
2020年1月1日以降を「令和(<4EE4><548C>) %Ey(+2)年(<5E74>)」

表記するというものになります。

ですので上記のような ja_JP ファイルを作成し、locale-gen をすると
下記のように新暦に対応することができます。

新暦対応後の図

 


最後に。

Windows や Linux のシステムがかなり柔軟に新暦対応させられる作りになっていることはおわかりいただけたかと思います。
 
ただ、これは一人のソフトウェア作者としてのコメントではありますが
全てのプラットフォームが上記で挙げたような簡単な方法で
すぐ対応出来るようになっているわけではありません。

 
また、上記のようなレジストリキーやファイルを参照するものであっても
(平成)31年から(令和)1年へ変わるわけですので
エラーが発生するシステムも十二分に考えられます。
 
ですので上記の方法で対応ができ、
ご利用のソフトウェアで問題なく稼働した場合でも
これは運が良かったという程度にお考えいただき、
ベンダーの正式対応を基本的にはお待ちいただくようにしてください。
 
上記のリスクにご理解いただけるかたで、新しいものに楽しみを感じるかたは
ぜひ自己責任において新暦対応を一足お先にお試しくださいませ。
なお、それによりデータ破損等が発生しても当方では責任を負いかねます。

・・というわけで。であであー。