Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
ELFバイナリ静的解析入門
Search
segfo
August 17, 2018
0
810
ELFバイナリ静的解析入門
segfo
August 17, 2018
Tweet
Share
More Decks by segfo
See All by segfo
RustでOS作りたい話
segfo
4
1k
Featured
See All Featured
A Philosophy of Restraint
colly
203
16k
Practical Orchestrator
shlominoach
186
10k
Distributed Sagas: A Protocol for Coordinating Microservices
caitiem20
330
21k
Visualization
eitanlees
146
15k
ピンチをチャンスに:未来をつくるプロダクトロードマップ #pmconf2020
aki_iinuma
111
49k
Side Projects
sachag
452
42k
Designing for humans not robots
tammielis
250
25k
YesSQL, Process and Tooling at Scale
rocio
170
14k
jQuery: Nuts, Bolts and Bling
dougneiner
61
7.6k
Bootstrapping a Software Product
garrettdimon
PRO
305
110k
Optimising Largest Contentful Paint
csswizardry
33
3k
Intergalactic Javascript Robots from Outer Space
tanoku
270
27k
Transcript
ELFバイナリ静的解析入門 PIEバイナリの静的シンボル解決 segfo
この資料を読む上で必要な知識 PIEの意味を理解していること(必須) 動的リンクライブラリは何のことか理解していること(必須) IntelCPUのエンディアンを理解していること。(必須) ELFバイナリの各種構造体を理解していること。(必須ではない) ↑大体なんとなく直感でわかればOK。 (構造体で言われても正直抽象的すぎて分からない)
このスライドの目的 32bitアプリケーションがPIE時に動的関数が直接呼び出しされる場合において ローダーがどのようにアプリケーション内のシンボルを解決しているのか。 ということに焦点を当てている。 これを理解することで、動的リンクについての理解を深めることができる。
ソースコード(test.c) #include<stdio.h> #include<stdlib.h> int main(){ char s[128]={0}; printf("hello world"); fgets(s,127,stdin);
exit(-1); return 0; }
コンパイルオプション gcc -m32 -shared test.c -o sharedObject
BinaryNinjaで見たときのmain関数 謎の関数1 printf関数?
BinaryNinjaで見たときのmain関数(続き) 謎の関数2 fgets関数? 謎の関数3 exit関数? _fini関数が赤線以下から開 始している。 BinaryNinjaがうまく解析で きていない _fini関数
ソースを持っているから、なんとなく分かるが... バイナリだけポイって渡されて、手元にBinaryNinjaしか無くて 「静的解析してね♥」とか言われたら? わっかんねーよ バーーーーーーーーーーーカ ってなる、でもIDA使ってるProに負けるのは悔しいから なんとしてでもBinaryNinjaだけで解析したい。
シンボル名解決に必要な3つのセクション 【.dynsym】 シンボルとアドレスの対応表。.rel.dynから参照される。 【.dynstr】 シンボル名が文字列でダーーーーっと書かれている。 stdinとかfgetsとかが書いてある。.dynsymから参照される。 【.rel.dyn】 再配置についての情報がたくさんかかれている 0x5d4をcallしていたら、それは.dynsymの何番を見れば.dynstr(シンボル)がわかるよ みたいな事が書いてある。
それが変数か関数かと言った種類も書いてある
sub_5d4が何の関数呼び出しか解決してみよう これ! 【余談】 赤枠(アドレス0x5d3)の命令は 自身+1のアドレスを呼んでいる。 このままでは命令として意味が成り立っていないため、 動かない。ローダーがこの命令を書き換える(動的リンク する)ことで正しい命令となる。
.rel.dynセクション 種別が02のみ以下の解釈 call対象アドレス call 0x5d4 種別 01=変数 02=関数 06=GOTシンボル解決用 08=共有ライブラリがロード
されたアドレスを加える シンボルのインデックス =6 シンボル(.dyn.sym)のインデック ス=ゼロから始まる
.dynsymセクション 0番目 1番目 2番目 3番目 4番目 5番目 6番目(今回の対象)
.dynsymセクション .dynstr先頭からのオ フセット (文字列へのオフ セットアドレス) サイズ 関数の配置アドレス ・上位8bit=bind 0=Local 1=Global
2=Weak ・下位8bit=Type 0=NOTYPE 1=OBJECT 2=FUNC
.dynstrセクション .dynstr先頭=0x274 0x274+0x8d=0x301 65 78 69 74 00 文字列:“exit”
結果 着目点:.textセクションに存在する、0x5d3の命令(call 0x5d4命令)は共有ライブラリの どの関数を呼ぶのか 0x5d4は.rel.dynセクションの7番目のエントリに存在する .dynsymの6番目のエントリに.dynstrの参照がある .dynstrセクションのオフセット0x8dのアドレスにシンボル名が存在する そのシンボル名は exit だった。 つまり、動的リンク時には、exit関数が0x5d3のcall命令にリンクされる =PLTを経由しない(LD_PRELOADが効かないということもわかる)
おまけ _fini関数が赤線以下から開 始している。 BinaryNinjaがうまく解析で きていない 【余談】 何故_fini関数がmain関数の一部として解析されているか。 gccはexit関数が呼ばれているので ret命令を置かなかったことが一つ。 さらにBNがこの関数をexit関数であることを理解していない。
そのため、バイナリ的に後続する関数である _fini関数の末尾ret命令まで main関数であると解析されてしまっている。
おわり