誰かが暇なときか現実逃避してる時に更新してますたぶん。

MSILなにそれな方はここが簡単でいいかも。

変数(クラスを除く)
型と値の記述?:
ローカル変数:ローカル変数を使ってみる。(.locals ldloc ldloca stloc)
大域変数:大域変数を使ってみる。(モジュールレベルの.field ldsfld ldsflda stsfld)
配列:配列に値を入れて取り出してみる。(newarr)

分岐
無条件分岐:無条件分岐命令を使ってみる。(br)
条件分岐:条件分岐命令を使ってみる。(分岐)
条件分岐2:条件分岐命令を使ってみる。(switch)
ループ:条件分岐命令を使ってみる。(ループ)

関数(クラスを除く)
関数の呼び出し:関数を呼び出す(call ldarg)
関数ポインタの呼び出し:関数ポインタを呼び出す(ldftn calli ldarg)

クラス
クラスの定義:クラスの定義とインスタンスの生成(newobj)
メンバ変数:メンバ変数の宣言と使用(ldfld stfld)
静的メンバ変数:静的メンバ変数の宣言と使用(ldsfld stsfld)
メンバ関数の呼び出し:メンバ関数の宣言と定義と呼び出し
静的メンバ関数の呼び出し:静的メンバ関数の宣言と定義と呼び出し
継承?:
カレントインスタンスの参照:C#:thisキーワード VB.NET:Meキーワード

例外処理
例外処理:(.try catch)

その他
HelloWorld:CILでHelloWorld
コメントとラベル:// /*〜*/ 〜:
コードの記述:C言語系並に柔軟です。
アセンブリマニフェスト?:(.assembly)
外部アセンブリの参照?:(.assembly extern)
モジュール化と再利用?:継ぎ接ぎによるアプリケーションの作成


ページ中の"C#では・・・"と"VB.NETでは・・・"のコードはそれぞれの言語で無理矢理書いた場合の例です。
例えばILのコード中でモジュールレベルの関数を使用している場合、C#ではモジュールレベルの関数を作成できないためC#では記述できません。



リバースエンジニアリング回避のためのメモ :

文字列検索による機能トレースの妨害

  • stringなマジックワードをそのまま埋め込まない - 古典的
    • 処理トレース関係 : メッセージボックス用文字列など
    • サービス保護関係 : URL、SQL、認証トークン、共有鍵など
      • 例えばrot13/base64/圧縮伸張するだけでも若干の効果
  • stringをchar配列にしてランダムな順番で文字を格納 - .NET1.1から有りやや古典的
  • GUIではできるだけ.nameの値指定を削除 - フォームデザイナが自動で指定した場合などに見逃されている場合あり


コール追跡の妨害

  • 関数ポインタの使用
  • jmpjmpiを使用する - ディスコンパイルの回避
  • 関数名や変数名を数字等にする(バイナリレベルでの難読化) - ディスコンパイルの回避(ただし自動で名前を付け直すディスコンパイラ有り)


変数追跡の妨害

  • クラス外のモジュールレベル関数・変数を使用する - ディスコンパイルの回避(完全なオブジェクト指向言語に限る)


ディスコンパイラ混乱の誘発

  • スタックには影響するが、処理には影響の無いコードを混ぜる


静的コード埋め込みによるディスコンパイル妨害


動的コード生成によるトレース妨害

  • エミッタ等を使用して実行時にコードを生成する
  • 「ディスコンパイラ混乱の誘発」と併せて使用すると相乗効果


ディスアセンブルされた場合のフロー解析妨害

  • dupとstore/loadや、cpblkを使用した参照先・参照元辿りの複雑化
  • スタックに影響する無意味な命令を実行しない場合、最低でもbranch系をできるだけ遠回し・複雑に使う - ネイティブでも使用される古典的方法
  • 変数追跡の妨害に加え、変数内容によりjmp/jmpi先を変更・branch先を変更するなど、コール追跡の妨害を強化


パターン認識型ディスコンパイラ対策

  • 一度使った難読化パターンを、そのまま他アプリケーションで使い回さない
  • ソースコードレベルではコピペ判定ツールに検出されないこと
  • 処理にJavaScriptなどインタプリタ言語エンジンを組み合わせる場合は、オートフォーマッタやeval()展開機能を持つ解析ソフトも考慮

対Lutz Roeder's .NET Reflector

ディスコンパイラ混乱の誘発

  • 関数名の違うオーバーロードを多用する
    • 継承によるメンバ関数のオーバーロードをファイル化プラグインが解決できない(オーバーロード先の関数名をオーバーロード元の関数名に追従できない)特性を利用

厳密には難読化でない気もするけど最終手段

ILコードとネイティブコードの混在によるトレース妨害

  • ネイティブコードの混じったマネージドC++を使う
  • アンマネージDLLを呼び出す


基本

.entrypoint:エントリポイント
.field:フィールドの宣言(大域変数、メンバ変数などの宣言に使用)
.locals:ローカル変数の宣言
.maxstack?:その関数で使用されるスタックの最大使用量
.method:関数の始まりを示す
.overloads?:その関数がオーバーロード関数であることを示す
.subsystem:OSから呼び出すサブシステムの指定(コンソールアプリにするか、Windowsアプリにするか、それとも… の指定はここ。)
.imagebase?:
.module?:
.publickeytoken?:
.ver?:
.custom?:
.hash?:
.mresource?:
.file?:
.corflags?:
.mresource?:
.namespace?:名前空間の始まりを示す
.assembly:
.try:例外処理

クラス関連

クラス関係はC#のキーワードと似てると思うのであまり説明要らないかもですが一応。

.class:クラスの始まりを示す
.ctor:コンストラクタ関数の名前
.cctor:静的コンストラクタ関数の名前
.extends?:そのクラスが継承クラスであることを示す
.implements?:そのクラスがインターフェイスを実装していることを示す
.override?:その関数がオーバーライド関数であることを示す


ansi?:
auto?:
beforeinitfield?:
cli managed?:
extern:
final?:
friend?:
hidebysig?:
initonly?:
instance?:
literal?:
native?:
newslot?:
private?:
public?:
rtspecialname?:
specialname?:
static?:
unsigned?:
virtual?:
catch?:例外処理
finally:例外処理
fault:例外処理
filter:例外処理
handler:例外処理


参照 : http://www.southern-storm.com.au/docs/pnettools_11.html#SEC58


変数
ldloc:load local variable the stack - ローカル変数をpush
ldloca:load local variable address - ローカル変数のアドレスをpush
stloc:pop value from stack to local variable - popしてローカル変数に格納
ldfld:load field of an object - クラスのメンバ変数をpush
ldflda?:load field address - クラスのメンバ変数のアドレスをpush
stfld:store into a field of an object - popしてクラスのメンバ変数に格納
ldsfld:load static field of a class - クラスの静的メンバ変数をpush
ldsflda:load static field address - クラスの静的メンバ変数のアドレスをpush
stsfld:store a static field of a class - popしてクラスの静的メンバ変数に格納

配列
newarr:create a zero-based、one-dimensional array - 1次元配列を作成しpush
ldlen?:load the length of an array - popした配列の長さをpush
ldelema?:load address of an element of an array - 配列の要素のアドレスをpush
ldelem:load an element of an array - 配列の要素をpush
stelem:store an element of an array - popして配列の要素に格納

定数
ldnull?:load a null pointer - ヌルポインタをpush(ガッガッ
ldc:load numeric constant - 定数をpush
ldstr:load literal string - 文字列をpush

スタック操作
dup?:duplicate the top value of stack - スタックの先頭の要素を複製してpush
pop?:remove the top element of the stack - スタックの先頭の要素を削除
ldind?:load value indirect onto the stack -
stind?:store value indirect from stack -

関数
call:call a method - 関数の呼び出し
callli:indirect method call - 関数ポインタの呼び出し
callvirt?:call a method associated、at runtime、with an object - 遅延バインディングを使用した関数の呼び出し
ret:return from method -
ldftn:load method pointer - 関数ポインタをpush
ldvirtftn?:load a virtual method pointer -
jmp:jump to method - 関数にジャンプ(retしても戻らない)
jmpi:jump via method pointer - 関数ポインタにジャンプ(retしても戻らない)

関数の引数
ldarg:load argument onto the stack - 引数をpush
ldarga?:load an argument address - 引数のアドレスをpush
starg?:store a value in an argument slot - popして引数に格納
arglist?:get argument list -

分岐
br:unconditional branch - 無条件分岐
brfalse:branch on false、null、or zero - false(0)またはnullの場合に分岐
brtrue:branch on non-false or non-null - false(0)またはnull以外の場合に分岐
beq?:branch on equal - == 等しい場合に分岐(2回popしてその値を比較し等しかったら分岐)
bge?:branch on greater then or equal to - >=
bgt?:>
ble?:=<
blt?:<
bne?:!=
switch:table switch on value - popした値によって指定したラベルに分岐。

数値演算
add?:+ (2回popしてそれらを足しその結果をpush)
sub?:-
mul?:*
div?:/
rem?:compute remainder - %(mod) 余りを計算。
neg?:negate - 符号の反転

比較演算
ceq?:compare equal - (2回popして等しいかどうか判断し結果をpush)
cgt?:compare greater than -
clt?:compare less than -
ckfinite?:check for a finite real number - 有限の実数であるかどうか調べる

論理演算
and?:&
or?:|
xor?:xor
not?:not - !
shl?:shift integer left - <<
shr?:shift integer right - >>

オブジェクト操作
conv?:data conversion - データの変換
cpobj?:copy a value type -
initobj?:initialize a value type -
ldobj?:copy value type to the stack -
stobj?:store a value type from the stack into memory
newobj:create a new object - オブジェクトの生成
castclass?:cast an object to a class - オブジェクトのクラスへのキャスト
isinst?:test if an object is an instance of a class or interface、returning NULL or an instance of that class or interface
popしたオブジェクトがクラスまたはインターフェイスのインスタンスかどうか調べる。
box?:convert value type to object reference - box化(型をオブジェクト参照に変換)
unbox?:Convert boxed value type to its raw form - box化を解除

エラー処理
throw?:throw an exception - 例外をthrow
rethrow?:rethrow the current exception -
endfinally:end finally clause of an exception block - .tryのfinally節から抜ける
leave:exit a protected region of code -

メモリ操作
cpblk:copy data from memory to memory - メモリブロック間のデータコピー(memcpy?)
initblk?:initialize a block of memory to a value - メモリブロックの初期化(memset?)
sizeof:load the size in bytes of a value type - (sizeof?)
localloc?:allocate space in the local dynamic memory pool - (malloc?)

未分類
nop:no operation - 何もしない。
break?:breakpoint instruction - ブレークポイントの設定
ann?:Annotations
ldtoken?:load the runtime representation of a metadata token -
endfilter?:end filter clause of SEH -
unaligned?:subsequent pointer instruction may be unaligned -
volatile?:subsequent pointer reference is volatile -
tail?:subsequent call terminates current method -
refanyval?:load the address out of a typed reference -
refanytype?:load the type out of a typed reference -
mkrefany?:push a typed reference on the stack -


英語でよければ.NET FrameworkのSDKにCILの解説が。

CIL

.Net

アセンブラ・コンパイラ・リンカ

  • Microsoft .NET Framework内 - %windir%\Microsoft.NET\Framework\v〜\ilasm.exe
  • Salamander .NET Native Compiler - .NETアセンブリをネイティブコードにコンパイル

ディスアセンブラ・ディスコンパイラ

パッケージャー

  • Spoon Studio - 旧Xenocode. Portableな実行を可能に. (e.g.: .NETアプリに.NETランタイムをインテグレートしてインストール不要に)

難読化


(Alpha2上に作成したものを移行@2005/07/06)


トップ 編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード 新規 一覧 単語検索 最終更新 リンク元 ヘルプ 最終更新のRSS xenowire
Last-modified: Thu, 25 Jan 2018 15:08:13 JST