忘備録

日々の調べ物をまとめる。アウトプットする。基本自分用。

アセンブラとの遭遇

先日↓の記事で知った「Dokugaku Dojo」なるコミュニティのミートアップに参加してきました。
「中級者エンジニア」ならではの悩み - zakisan's blog

そこで行われたプレゼンを通してアセンブラにちょこっと触れたので、その時やったことをまとめておく。

↓プレゼンの資料

www.slideshare.net

当方の環境

Mac OS X 10.10

やったこと

Homebrewのインストール

binutilsのインストールにHomebrewが必要なので、インスコ
※Homebrewとは

MacOSX - パッケージ管理システム Homebrew - Qiita

Homebrew(ホームブルー)とは、Mac OS X オペレーティングシステム上でソフトウェアの導入を単純化するパッケージ管理システムのひとつです。yum や apt-get の類の一つです。

お恥ずかしい話、Homebrewは「聞いたことあるけどおいしいのかな?」って感じでした。

↓インストールスクリプトが載ってます。

Homebrew — OS X 用パッケージマネージャー

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とは

組み込み Linux 開発の手引き - GNU開発ツール

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
オプションをよく使うそうです。

Man page of objdump

-D (--disassemble-all)
命令を含むと思われるセクションだけでなく、全てのセクションを逆アセンブルする。
-S (--source)
(可能であれば) ソースコードを逆アセンブル結果と混在させて表示する。 -d が暗黙のうちに指定される。

ちなみにMacだとobjdumpではなくgobjdumpみたいです。

で、(g)objdumpをすると以下のような出力がされます。
f:id:mktktmr:20151202080153p:plain

なんだか色々と出力されていますが。。。

セクション .text の逆アセンブル:

0000000100000f00 <_main>:

以下が、main関数のコードと思われます。

期待している結果を得るには、if文の条件を変えればいいので、
それっぽい命令をみつけます。
movが代入
cmpが比較なので。。。 f:id:mktktmr:20151202192154p:plain

この辺りが分岐の判定をしているのだろうと当たりがつきます。
そして、この分岐の命令と思われる機械語コードによってバイナリの書き換えを行う場所を特定します。

バイナリファイルの編集

参考: vimでバイナリを表示し、値を変更したい - rderaログ

vi -b sample

vimで開くと。。。

f:id:mktktmr:20151202135005p:plain

なるほど。分からん。
なので、16進数ダンプ形式に変換。
ファイルを開いたまま以下コマンドを叩く。

:%!xxd

すると。。。

f:id:mktktmr:20151202135335p:plain

なんとなくわかりそうな心持ちはする状態になりました。

objdumpによって得た情報で比較をしている機械語コードに検討がついているので、
そのあたりを探す。

f:id:mktktmr:20151202192154p:plain

だったので。。。

f:id:mktktmr:20151210132822p:plain

この辺?

で、

if (key >= 1 )

の1と思われる
f801
f800
書き換える

f:id:mktktmr:20151210133729p:plain f:id:mktktmr:20151210133730p:plain

編集が終わったので「:w」としたくなりますが。。。

:%!xxd -r

でバイナリに戻すと編集した内容が反映されます。

んで、書き込んで終了。

:wq

編集したファイルを実行

Makoto-Air:tmp makoto$ ./sample 
FLAGS:dokugakudojo

キタ━━━━(゚∀゚)━━━━!!







。。。ただ

何故

if (key >= 1 )

の1が
f801になるのか
とかよく分かってない^^;

そのあたり資料に参考図書が載っていたので、手にとって勉強したいです。

所感

耳にしたことしかなかったアセンブラに触れることができて少し興奮しました。
今回のプレゼンを受けていなかったら、一生アセンブラに触らなかったかも。。

発表者の末永さんにも感謝ですね。
あと、オチまでの流れがすごく好き 笑。