狠狠撸

狠狠撸Share a Scribd company logo
発表者 : 僻地のプログラマ kmt-t
?   ハンドルネーム
    ? 正式にはkmt-t
    ? はてなID : kmt-t2
    ? Twitter ID : kmt_t
?   僻地(鳥取県)出身です
    ? 大阪まで出稼ぎに出ています
?   得意分野など
    ? プログラミング言語はC++/C#など
    ? 組み込みではミドルウェア開発を得意にしています
     ? 2D/3Dグラフィックスおよび画像処理
     ? ファイルシステム
?   今回の発表はDalvik仮想マシン3部作の最後です
    1. Dalvik仮想マシンのアーキテクチャ
    2. Dalvikバイトコードのリファレンスの読み方
    3. 詳解DEXフォーマット ← 今回はこれ!
?   発表の目的
    1. Dalvik仮想マシンのソースコードを誰でも読めるように!
    2. Dalvik仮想マシンに関するみんなのリテラシを上げる!
    3. より深い部分の発表をするための下地をつくる!
?   Dalvik仮想マシンの実行ファイル
    ?   Windowsで言えばPEファイルに相当します
    ?   Javaで言えばクラスファイルに相当します
    ?   Javaのクラスファイルとは形式が違います
    ?   配布する場合は生のDEXファイルではなくパッケージされた
        apkファイルにすることが殆どです
?   Dalvik仮想マシン同様シンプルで結構簡単です
    ? 理解するとバイトコードの動的生成、バイトコードエンジニアリ
      ングなどができるようになります
?   リファレンス
    ? $ANDROID_SOURCE/dalvik/docs/dex-format.html
?   Linuxにおけるobjdump相当
    ? Android SDKに含まれています
    ? このツールでDEXファイルのいろいろな情報が抜き出せます
    ? 実用的にはこのツールが不自由なく使えるレベルのDEXファ
      イルフォーマットの知識があれば充分
?   代表的なオプション
    オプション   説明
    -f      ヘッダ(クラスやメソッドの定義など)のサマリーの表示
    -h      ヘッダ(クラスやメソッドの定義など)の詳細の表示
    -d      コードの逆アセンブルの表示
详解顿别虫ファイルフォーマット
?   ファイルは以下の領域に分割
        ヘッダ領域          string_ids領域
        type_ids領域     proto_ids領域
        field_ids領域    method_ids領域
        class_defs領域   data領域
        link_data領域


?   data領域、link_data領域に可変長データを格納
    ? link_data領域はアンドキュメンテッド
    ? それ以外の領域には固定長のデータしか格納されない
アイテム名         内容
magic         “dex?n035?0” (固定値)
checksum      alder32によるチェックサム。signatureでも同様
              の検出ができるが、ファイルの破損チェック用計算
              コストの問題から通常はこちらを使った方が良い
signature     SHA-1によるハッシュ値。ファイルを一意に識別す
              るために使用できる。配布元の正しいハッシュ値と
              比較すれば改ざんされていることは簡単に検出で
              きる。計算コストが高いので毎起動時に検査する
              のは難しい
file_size     ファイルサイズ
header_size   ヘッダサイズ。固定長
endian_tag    固定データ(0x12345678)。ファイルのエンディア
              ン識別用
アイテム名             内容
link_size         link_data領域のバイト数
link_off          link_data領域へのオフセット
map_off           data領域のレイアウトを示すmapへのオフセット。
                  基本的にmapの情報は他の情報の冗長データに
                  なっている(ファイルかデータを読み出す際には必
                  須ではない)
string_ids_size   文字列定数プールに格納されている文字列の数。
string_ids_off    string_ids領域へのオフセット
type_ids_size     type_ids領域のデータの数
type_ids_off      type_ids領域へのオフセット
proto_ids_size    proto_ids領域のデータの数
proto_ids_off     proto_ids領域へのオフセット
アイテム名             内容
field_ids_size    field_ids領域のデータ数
field_ids_off     field_ids領域へのオフセット
method_ids_size   method_ids領域のデータ数
method_ids_off    method_ids領域へのオフセット
class_defs_size   class_defs領域のデータの数
class_defs_off    class_defs領域へのオフセット
data_size         data領域のバイト数
data_off          data領域へのオフセット
?   定数文字列プールを格納する領域
?   以下の情報の配列(データ数はヘッダに記述)
データ名              型名        内容
string_data_off   uint      data領域の定数文字列データへのオフセット

?   オフセットが指すdata領域には以下のデータが格納
データ名              型名        内容
utf16_size        uleb128   MUFT-8文字列をUTF-16にデコードしたとき
                            の文字列長
data              MUTF-8    文字列データ
?   LEB128
    ? DWORF3でも使われているデータ形式らしいです
    ? 可変長整数データ型です
     ? Byteの最上位bitが立っている場合は次のByteはその上位7bit
       が格納されています。byteの最上位ビットが落ちている場合は
       データ終了
    ? 値の小さな整数はデータ長が短くなります
    ? 可変長なのでdata領域のみに存在します
?   余談
    ? 実際にはDEXはapk(ZIP)でパッケージされるのであんまり意
      味が無い(圧縮したらサイズは同じぐらいになる)のでは
?   UTF-16の一文字を1~3byteにエンコードした形式
    ?   Javaバイトコードでも使われています
    ?   Java、Dalvikともに内部の文字コードはUTF-16です
    ?   MUTF-8の方がUTF-8より都合がいいです
    ?   エンコード元がUTF-16なのでサロゲートペアは出現します
    ?   Linuxでのワイド文字列はUTF-32なので取り扱いは注意
    ?   可変長なのでdata領域のみに存在します
?   余談
    ? あんまり意味が無いと思うんですが(UTF-16そのままでもあ
      まり差が出ないはず)、がんばりすぎですよね
?   DEXファイルで参照されている型のテーブル
 ?   以下の情報の配列(データ数はヘッダに記述)
データ名                        型名     内容
descriptor_idx              uint   型名を表すTypeDiscriptor文字列のID
                                   (string_ids領域ののインデックス)


 ?   TypeDiscriptorは以下のフォーマットの文字列
文字列                                型名
V, Z, B, S, C, I, J, F, D          プリミティブ型
Lfully/qualified/Name;             クラス型 (この場合”fully.qualified.Name”)
[TypeDescrioter                    配列型 (“[I”ならintの配列)
?   DEXファイルで参照されているメソッド型のテーブル
?   以下の情報の配列(データ数はヘッダに記述)
データ名              型名     内容
shorty_idx        uint   型名を表すShortTypeDiscriptor文字列の
                         ID(string_ids領域のインデックス)
return_type_idx   uint   戻り値型のID
                         (type_ids領域のインデックス)
parameters_off    uint   パラメータ型のIDのリストへのオフセット。オフ
                         セットの指す先はdata領域
?   クラスのフィールド情報を格納する領域
?   以下の情報の配列(データ数はヘッダに記述)
データ名        型名       内容
class_idx   ushort   フィールドを所有するクラス型のID
                     (type_ids領域のインデックス)
type_idx    ushort   フィールド型のID
                     (type_ids領域のインデックス)
name_idx    uint     フィールド名の文字列ID
                     (string_ids領域のインデックス)
?   クラスのメソッド情報を格納する領域
?   以下の情報の配列(データ数はヘッダに記述)
データ名        型名       内容
class_idx   ushort   メソッドを所有するクラス型のID
                     (type_ids領域のインデックス)
proto_idx   ushort   メソッド型のID
                     (proto_ids領域のインデックス)
name_idx    uint     メソッド名の文字列ID
                     (string_ids領域のインデックス)
?   クラス情報を格納する領域
?   以下の情報の配列(データ数はヘッダに記述)
データ名                型名     内容
class_idx           uint   クラス型のID (type_ids領域のインデックス)
access_flags        uint   アクセス属性フラグ
superclass_idx      uint   親クラス型のID (type_ids領域のインデックス)
interfaces_off      uint   継承インターフェイス型のリストへのオフセット
source_file_idx     uint   ソースファイル名の文字列ID
annotations_off     uint   アノテーション情報のオフセット
class_data_off      uint   class_dataへのオフセット
static_values_off   uint   静的フィールドの初期値.
?   data領域に含まれるデータ一覧 (1/2)
データ名                  内容
MapList               ファイルデータのレイアウト情報
StringData            文字列データ
TypeList              型IDのリスト
AnnotationDirectory   クラスとそのフィールド、メソッドのすべてのアノテーショ
                      ン情報の集まり
AnnotationSetRef      アノテーションのリストのリスト
AnnotationSet         アノテーションのリスト
Annotation            アノテーション
EncodedArray          クラスの初期値、アノテーションの設定値を圧縮した
                      データ
?   data領域に含まれるデータ一覧 (2/2)
データ名         内容
ClassData    クラス情報
Code         メソッドのバイトコードの情報
DebugInfo    デバッグ情報
データ名                   型名               内容
static_fields_size     uleb128          静的フィールドの数
instance_fields_size   uleb128          インスタンスフィールドの数
direct_methods_size    uleb128          コンストラクタ、静的メソッドの数
virtual_methods_size   uleb128          仮想メソッドの数
static_fields          encoded_field    静的フィールドの数
                       の配列
instance_fields        encoded_field    インスタンスフィールドの情報
                       の配列
direct_methods         encoded_method   コンストラクタ、静的メソッドの
                       の配列              情報
virtual_methods        encoded_method   仮想メソッドの情報
                       の配列
?   encoded_field構造体
データ名              型名        内容
field_idx_diff    Uleb128   フィールドID (field_ids領域のインデックス)
                            差分前のフィールドの値との差分
access_flags      Uleb128   アクセスフラグ


?   encoded_method構造体
データ名              型名        内容
method_idx_diff   uleb128   メソッドID (method_ids領域のインデックス)
                            差分前のメソッドの値との差分
access_flags      uleb128   アクセスフラグ
code_off          uleb128   コード構造体のオフセット
データ名             型名                 内容
registers_size   ushort             メソッドで使用するレジスタ数
ins_size         ushort             引数の数
outs_size        ushort             出力引数の数
tries_size       ushort             tryスコープの数
debug_info_off   uint               デバッグ情報のオフセット
insns_size       uint               バイトコードの16bitユニット数
insns            ushortの配列          バイトコード命令列
padding          ushort(optional)   アライメントのためのパディング
tries            tryスコープの配列         tryスコープの情報
handlers         ハンドラの配列            例外補足ハンドラのリスト
详解顿别虫ファイルフォーマット

More Related Content

详解顿别虫ファイルフォーマット

  • 2. ? ハンドルネーム ? 正式にはkmt-t ? はてなID : kmt-t2 ? Twitter ID : kmt_t ? 僻地(鳥取県)出身です ? 大阪まで出稼ぎに出ています ? 得意分野など ? プログラミング言語はC++/C#など ? 組み込みではミドルウェア開発を得意にしています ? 2D/3Dグラフィックスおよび画像処理 ? ファイルシステム
  • 3. ? 今回の発表はDalvik仮想マシン3部作の最後です 1. Dalvik仮想マシンのアーキテクチャ 2. Dalvikバイトコードのリファレンスの読み方 3. 詳解DEXフォーマット ← 今回はこれ! ? 発表の目的 1. Dalvik仮想マシンのソースコードを誰でも読めるように! 2. Dalvik仮想マシンに関するみんなのリテラシを上げる! 3. より深い部分の発表をするための下地をつくる!
  • 4. ? Dalvik仮想マシンの実行ファイル ? Windowsで言えばPEファイルに相当します ? Javaで言えばクラスファイルに相当します ? Javaのクラスファイルとは形式が違います ? 配布する場合は生のDEXファイルではなくパッケージされた apkファイルにすることが殆どです ? Dalvik仮想マシン同様シンプルで結構簡単です ? 理解するとバイトコードの動的生成、バイトコードエンジニアリ ングなどができるようになります ? リファレンス ? $ANDROID_SOURCE/dalvik/docs/dex-format.html
  • 5. ? Linuxにおけるobjdump相当 ? Android SDKに含まれています ? このツールでDEXファイルのいろいろな情報が抜き出せます ? 実用的にはこのツールが不自由なく使えるレベルのDEXファ イルフォーマットの知識があれば充分 ? 代表的なオプション オプション 説明 -f ヘッダ(クラスやメソッドの定義など)のサマリーの表示 -h ヘッダ(クラスやメソッドの定義など)の詳細の表示 -d コードの逆アセンブルの表示
  • 7. ? ファイルは以下の領域に分割 ヘッダ領域 string_ids領域 type_ids領域 proto_ids領域 field_ids領域 method_ids領域 class_defs領域 data領域 link_data領域 ? data領域、link_data領域に可変長データを格納 ? link_data領域はアンドキュメンテッド ? それ以外の領域には固定長のデータしか格納されない
  • 8. アイテム名 内容 magic “dex?n035?0” (固定値) checksum alder32によるチェックサム。signatureでも同様 の検出ができるが、ファイルの破損チェック用計算 コストの問題から通常はこちらを使った方が良い signature SHA-1によるハッシュ値。ファイルを一意に識別す るために使用できる。配布元の正しいハッシュ値と 比較すれば改ざんされていることは簡単に検出で きる。計算コストが高いので毎起動時に検査する のは難しい file_size ファイルサイズ header_size ヘッダサイズ。固定長 endian_tag 固定データ(0x12345678)。ファイルのエンディア ン識別用
  • 9. アイテム名 内容 link_size link_data領域のバイト数 link_off link_data領域へのオフセット map_off data領域のレイアウトを示すmapへのオフセット。 基本的にmapの情報は他の情報の冗長データに なっている(ファイルかデータを読み出す際には必 須ではない) string_ids_size 文字列定数プールに格納されている文字列の数。 string_ids_off string_ids領域へのオフセット type_ids_size type_ids領域のデータの数 type_ids_off type_ids領域へのオフセット proto_ids_size proto_ids領域のデータの数 proto_ids_off proto_ids領域へのオフセット
  • 10. アイテム名 内容 field_ids_size field_ids領域のデータ数 field_ids_off field_ids領域へのオフセット method_ids_size method_ids領域のデータ数 method_ids_off method_ids領域へのオフセット class_defs_size class_defs領域のデータの数 class_defs_off class_defs領域へのオフセット data_size data領域のバイト数 data_off data領域へのオフセット
  • 11. ? 定数文字列プールを格納する領域 ? 以下の情報の配列(データ数はヘッダに記述) データ名 型名 内容 string_data_off uint data領域の定数文字列データへのオフセット ? オフセットが指すdata領域には以下のデータが格納 データ名 型名 内容 utf16_size uleb128 MUFT-8文字列をUTF-16にデコードしたとき の文字列長 data MUTF-8 文字列データ
  • 12. ? LEB128 ? DWORF3でも使われているデータ形式らしいです ? 可変長整数データ型です ? Byteの最上位bitが立っている場合は次のByteはその上位7bit が格納されています。byteの最上位ビットが落ちている場合は データ終了 ? 値の小さな整数はデータ長が短くなります ? 可変長なのでdata領域のみに存在します ? 余談 ? 実際にはDEXはapk(ZIP)でパッケージされるのであんまり意 味が無い(圧縮したらサイズは同じぐらいになる)のでは
  • 13. ? UTF-16の一文字を1~3byteにエンコードした形式 ? Javaバイトコードでも使われています ? Java、Dalvikともに内部の文字コードはUTF-16です ? MUTF-8の方がUTF-8より都合がいいです ? エンコード元がUTF-16なのでサロゲートペアは出現します ? Linuxでのワイド文字列はUTF-32なので取り扱いは注意 ? 可変長なのでdata領域のみに存在します ? 余談 ? あんまり意味が無いと思うんですが(UTF-16そのままでもあ まり差が出ないはず)、がんばりすぎですよね
  • 14. ? DEXファイルで参照されている型のテーブル ? 以下の情報の配列(データ数はヘッダに記述) データ名 型名 内容 descriptor_idx uint 型名を表すTypeDiscriptor文字列のID (string_ids領域ののインデックス) ? TypeDiscriptorは以下のフォーマットの文字列 文字列 型名 V, Z, B, S, C, I, J, F, D プリミティブ型 Lfully/qualified/Name; クラス型 (この場合”fully.qualified.Name”) [TypeDescrioter 配列型 (“[I”ならintの配列)
  • 15. ? DEXファイルで参照されているメソッド型のテーブル ? 以下の情報の配列(データ数はヘッダに記述) データ名 型名 内容 shorty_idx uint 型名を表すShortTypeDiscriptor文字列の ID(string_ids領域のインデックス) return_type_idx uint 戻り値型のID (type_ids領域のインデックス) parameters_off uint パラメータ型のIDのリストへのオフセット。オフ セットの指す先はdata領域
  • 16. ? クラスのフィールド情報を格納する領域 ? 以下の情報の配列(データ数はヘッダに記述) データ名 型名 内容 class_idx ushort フィールドを所有するクラス型のID (type_ids領域のインデックス) type_idx ushort フィールド型のID (type_ids領域のインデックス) name_idx uint フィールド名の文字列ID (string_ids領域のインデックス)
  • 17. ? クラスのメソッド情報を格納する領域 ? 以下の情報の配列(データ数はヘッダに記述) データ名 型名 内容 class_idx ushort メソッドを所有するクラス型のID (type_ids領域のインデックス) proto_idx ushort メソッド型のID (proto_ids領域のインデックス) name_idx uint メソッド名の文字列ID (string_ids領域のインデックス)
  • 18. ? クラス情報を格納する領域 ? 以下の情報の配列(データ数はヘッダに記述) データ名 型名 内容 class_idx uint クラス型のID (type_ids領域のインデックス) access_flags uint アクセス属性フラグ superclass_idx uint 親クラス型のID (type_ids領域のインデックス) interfaces_off uint 継承インターフェイス型のリストへのオフセット source_file_idx uint ソースファイル名の文字列ID annotations_off uint アノテーション情報のオフセット class_data_off uint class_dataへのオフセット static_values_off uint 静的フィールドの初期値.
  • 19. ? data領域に含まれるデータ一覧 (1/2) データ名 内容 MapList ファイルデータのレイアウト情報 StringData 文字列データ TypeList 型IDのリスト AnnotationDirectory クラスとそのフィールド、メソッドのすべてのアノテーショ ン情報の集まり AnnotationSetRef アノテーションのリストのリスト AnnotationSet アノテーションのリスト Annotation アノテーション EncodedArray クラスの初期値、アノテーションの設定値を圧縮した データ
  • 20. ? data領域に含まれるデータ一覧 (2/2) データ名 内容 ClassData クラス情報 Code メソッドのバイトコードの情報 DebugInfo デバッグ情報
  • 21. データ名 型名 内容 static_fields_size uleb128 静的フィールドの数 instance_fields_size uleb128 インスタンスフィールドの数 direct_methods_size uleb128 コンストラクタ、静的メソッドの数 virtual_methods_size uleb128 仮想メソッドの数 static_fields encoded_field 静的フィールドの数 の配列 instance_fields encoded_field インスタンスフィールドの情報 の配列 direct_methods encoded_method コンストラクタ、静的メソッドの の配列 情報 virtual_methods encoded_method 仮想メソッドの情報 の配列
  • 22. ? encoded_field構造体 データ名 型名 内容 field_idx_diff Uleb128 フィールドID (field_ids領域のインデックス) 差分前のフィールドの値との差分 access_flags Uleb128 アクセスフラグ ? encoded_method構造体 データ名 型名 内容 method_idx_diff uleb128 メソッドID (method_ids領域のインデックス) 差分前のメソッドの値との差分 access_flags uleb128 アクセスフラグ code_off uleb128 コード構造体のオフセット
  • 23. データ名 型名 内容 registers_size ushort メソッドで使用するレジスタ数 ins_size ushort 引数の数 outs_size ushort 出力引数の数 tries_size ushort tryスコープの数 debug_info_off uint デバッグ情報のオフセット insns_size uint バイトコードの16bitユニット数 insns ushortの配列 バイトコード命令列 padding ushort(optional) アライメントのためのパディング tries tryスコープの配列 tryスコープの情報 handlers ハンドラの配列 例外補足ハンドラのリスト