C#でもILGeneratorでダイナミックにToStringしたい
はじめに
動的にToString
するのに定評がある[要出典]弊社ですが、ライブラリを追加するレベルでもないけど手軽に1ソースコードを追加するだけでパパッと使えるものが欲しいな~と考えておりました。
と、いうわけで作りました。
縛り内容
ゲーム実況等では縛りとしていくつかルールを決めてプレイすることがありますよね。
今回は弊社もいくつか縛りを設けて実装してみようと思います。
- 1ソースコード・100行以内で実装
- Visual Studio 2010・.NET Framework 4.0でビルドできるコードにする
2番目についてはまぁ涙を拭けよといった感じですが、まぁアレがアレですよね。
コード
おわりに
まぁやっていることはSigilを使ったアレと全く一緒なんで特に解説もいらないかな。
おわり
VB.NETでもWinDbgしたい
はじめに
この記事はWinDbgで.NET Frameworkのデバッグをするときのコマンドの備忘録です。
解説はありません。希望もありません。
ダンプの取得
ダンプは別途ソフトウェアをインストールする必要なく、タスクマネージャから取得することが可能。
しかし、ダンプを取得するプロセスのビット数に応じてタスクマネージャのビット数を選択する必要がある。
- 32bit Windows
- 常に32bitタスクマネージャ(通常起動したタスクマネージャ)
- 64bit Windows
- 64bitプロセス
- 64bitタスクマネージャ(通常起動したタスクマネージャ)
- 32bitプロセス
- 32bitタスクマネージャ
%windir%\SysWOW64\taskmgr.exe
- 32bitタスクマネージャ
- 64bitプロセス
当該プロセスがどのビット数で動作しているかはタスクマネージャの詳細
タブ→プラットフォーム
(Windows 10)から確認が可能。
SOSのロード
- ~.NET 3.5
.loadby sos mscorwks
- .NET 4 ~
.loadby sos clr
メソッドにブレークポイントを貼る
!bpmd
はsos.dll
のロードが必要。
-
!bpmd <assembly> <namespace>.<class>.<method>
!bpmd ConsoleApplication2.exe ConsoleApplication2.Module1.Add
ジェネリッククラス
!bpmd <assembly> <namespace>.<class>`<type argument count>.<method>
!bpmd mscorlib.dll System.Collections.Generic.List`1.Add
ジェネリックメソッド
How to add a breakpoint in a managed generic method in windbg (sos) – I know the answer (it's 42)
JITコンパイル済みネイティブアドレスからMethodDescを検索
0:000> !clrstack OS Thread Id: 0x2ec0 (0) Child SP IP Call Site 012ff14c 0192056e ConsoleApplication2.Module1.Hoge[[System.Double, mscorlib]](Double) [C:\Users\jyuch\Documents\Visual Studio 2015\Projects\ConsoleApplication2\ConsoleApplication2\Module1.vb @ 19] 012ff164 019204c2 ConsoleApplication2.Module1.Main() [C:\Users\jyuch\Documents\Visual Studio 2015\Projects\ConsoleApplication2\ConsoleApplication2\Module1.vb @ 10] 012ff2e8 73e81376 [GCFrame: 012ff2e8] 0:000> !ip2md 0192056e MethodDesc: 01444dcc Method Name: ConsoleApplication2.Module1.Hoge[[System.Double, mscorlib]](Double) Class: 0144159c MethodTable: 01444d70 mdToken: 06000011 Module: 01443fbc IsJitted: yes CodeAddr: 01920550 Transparency: Critical Source file: C:\Users\jyuch\Documents\Visual Studio 2015\Projects\ConsoleApplication2\ConsoleApplication2\Module1.vb @ 19
MethodDescからILをダンプ
0:000> !dumpil 01444dcc ilAddr = 00e72214 IL_0000: nop IL_0001: ldarga.s VAR OR ARG 0 IL_0003: constrained. <unknown token type 1b000000> IL_0009: callvirt System.Object::ToString IL_000e: stloc.0 IL_000f: br.s IL_0011 IL_0011: ldloc.0 IL_0012: ret
おわりに
わあい
おまけ
よさげ
VB.NETは解析されやすいのか?(その2)
はじめに
前回はildasm
を用いた逆アセンブルとプログラムに出現する文字列から当該処理を行う箇所を特定し、特定の処理の迂回をやってみました。
今回はデバッガを用いて実際の動作を覗いてみましょう。
動的解析
ところで、前回アセンブラを用いてILコードから実行ファイルを生成したときのコマンドをもう一度確認してみましょう。
>ilasm SuperUsefulApplication.il /exe /debug=impl /resource=SuperUsefulApplication.res /output=SuperUsefulApplication2.exe
ここで重要なのが/debug=impl
の部分です。
このオプションでデバッグシンボルを一緒に生成しています。
プログラムを起動し、デバッガをアタッチしてみましょう。 なお、ここではVisual Studio 2015 community update 3を使用しています。
デバッグ->プロセスにアタッチ
で一覧から目的のプロセスを見つけ、アタッチします。
ところで、このアプリケーションの処理内容について説明していませんでしたね。 文字列を入力するとその文字が格納され、なにも入力しないと入力した逆順に文字列が返されるようです。
なにそれただのスタックじゃん。なんだろな~。どうやって実装しているんだろうな~。気になるなぁ~。
前回の逆アセンブルコードから、SuperUsefulApplication.SuperUsefulClass`1<string>::Pop()
とSuperUsefulApplication.SuperUsefulClass`1<string>::Push()
が中核的な処理をつかさどっているようです。
ですので、この二つのメソッドにブレークポイントを設定してみましょう。
デバッグ->ブレークポイントの作成->関数のブレークポイント
からPop
とPush
にブレークポイントを設定します。
文字列を4つ程突っ込んでデバッガで内部状態を確認してみましょう。
ローカル変数を確認すると、線形リストでスタックを実装しているようです。
このアプリケーションは単純なのでここで終わりですが、もっと複雑なアプリケーション/ライブラリの場合でも普段と同じようにデバッグができるでしょう。
おわりに
このように、マネージドアプリケーションはリバースエンジニアリングに対して非常に脆弱であることが分かります。
リバースエンジニアリングに対する防御策としては、
などが挙げられます。
ロジックの重要度と実施するコストとを勘案していい感じにアレすればいいと思います。
おわり