アセンブラとの遭遇
先日↓の記事で知った「Dokugaku Dojo」なるコミュニティのミートアップに参加してきました。
「中級者エンジニア」ならではの悩み - zakisan's blog
そこで行われたプレゼンを通してアセンブラにちょこっと触れたので、その時やったことをまとめておく。
↓プレゼンの資料
当方の環境
Mac OS X 10.10
やったこと
Homebrewのインストール
binutilsのインストールにHomebrewが必要なので、インスコ。
※Homebrewとは
MacOSX - パッケージ管理システム Homebrew - Qiita
Homebrew(ホームブルー)とは、Mac OS X オペレーティングシステム上でソフトウェアの導入を単純化するパッケージ管理システムのひとつです。yum や apt-get の類の一つです。
お恥ずかしい話、Homebrewは「聞いたことあるけどおいしいのかな?」って感じでした。
↓インストールスクリプトが載ってます。
ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)" # 正常にインストールされたか確認 Makoto-Air:tmp makoto$ brew doctor Your system is ready to brew.
binutilsのインスコ
brew install binutils
※binutilsとは
binutilsというパッケージには、アセンブラであるasコマンドやローダであるld以外にも組み込みLinux開発を行う上で重要なコマンドが含まれています。
サンプルのCソース
sample.c/sample.c at master · asmsuechan/sample.c · GitHub
sample.c
#include<stdio.h> int main(void){ int key = 0; if(key >= 1){ printf("FLAGS:dokugakudojo\n"); }else{ printf("wrong key\n"); } return 0; }
keyが1以上なら"FLAGS:dokugakudojo\n"
それ以外なら"wrong key\n"が出力されるといったシンプルなサンプルです。
このソースをコンパイルして実行すると"wrong key\n"が出力されます。
んで、今回やることはコンパイルされたオブジェクトコードを逆アセンブルして解析し、
keyの値を書き換え、"FLAGS:dokugakudojo\n"を出力しようというものです。
コンパイル及び実行
gcc -o sample sample.c
./sample
wrong key
"wrong key"が出力されました。
これを"FLAGS:dokugakudojo"になるようにオブジェクトコードを書き換えます。
逆アセンブル
gobjdump -S sample
※(g)objdumpとは
組み込み Linux 開発の手引き - GNU開発ツール
登壇者の方によると
-S
-D
オプションをよく使うそうです。
-D (--disassemble-all)
命令を含むと思われるセクションだけでなく、全てのセクションを逆アセンブルする。
-S (--source)
(可能であれば) ソースコードを逆アセンブル結果と混在させて表示する。 -d が暗黙のうちに指定される。
ちなみにMacだとobjdumpではなくgobjdumpみたいです。
で、(g)objdumpをすると以下のような出力がされます。
なんだか色々と出力されていますが。。。
セクション .text の逆アセンブル: 0000000100000f00 <_main>:
以下が、main関数のコードと思われます。
期待している結果を得るには、if文の条件を変えればいいので、
それっぽい命令をみつけます。
movが代入
cmpが比較なので。。。
この辺りが分岐の判定をしているのだろうと当たりがつきます。
そして、この分岐の命令と思われる機械語コードによってバイナリの書き換えを行う場所を特定します。
バイナリファイルの編集
参考: vimでバイナリを表示し、値を変更したい - rderaログ
vi -b sample
vimで開くと。。。
なるほど。分からん。
なので、16進数ダンプ形式に変換。
ファイルを開いたまま以下コマンドを叩く。
:%!xxd
すると。。。
なんとなくわかりそうな心持ちはする状態になりました。
objdumpによって得た情報で比較をしている機械語コードに検討がついているので、
そのあたりを探す。
だったので。。。
この辺?
で、
if (key >= 1 )
の1と思われる
f801を
f800に
書き換える
編集が終わったので「:w」としたくなりますが。。。
:%!xxd -r
でバイナリに戻すと編集した内容が反映されます。
んで、書き込んで終了。
:wq
編集したファイルを実行
Makoto-Air:tmp makoto$ ./sample FLAGS:dokugakudojo
キタ━━━━(゚∀゚)━━━━!!
。。。ただ
何故
if (key >= 1 )
の1が
f801になるのか
とかよく分かってない^^;
そのあたり資料に参考図書が載っていたので、手にとって勉強したいです。
所感
耳にしたことしかなかったアセンブラに触れることができて少し興奮しました。
今回のプレゼンを受けていなかったら、一生アセンブラに触らなかったかも。。
発表者の末永さんにも感謝ですね。
あと、オチまでの流れがすごく好き 笑。