簡単な C プログラムを AMD64 向けにコンパイルして radare2 でディスアセンブルしてみよう!(Part 1)
June 14, 2020

僕はまったく基礎がなっていないことで世界的に有名なのですが、やはりこのままではいけないと思い、少し勉強することにしました。

適当なことを書いている可能性もたぶんにあるため、なにか間違っているときはご遠慮なく Twitterツイキャス でご指摘等いただけますと幸甚です…。

コードを書くとはどういうことか考えます


まずそもそもなぜコードを書くかというと、たとえばホームページや Web サービスを作ったり、めんどくさい作業や計算などを自分の代わりにやらせたり、などいろいろ目的はあると思います。まあもちろん 「コードを書くこと自体が最高」 みたいな変た…根っからのプログラミング好き、みたいな人もいるかと思います。

どのような場合でもたいがい

1. 人間がまずはコードを書く。
2. それをコンピュータが実行する。
3. 結果としてコードで実現したかったなにかがコンピュータにより実現される(あるいはコードがへぼすぎて何も起こらない、予想外のことが起こる、など)

という流れとなるかと思います。

ここで、コンピュータは人間の言葉を理解することができません。直接 「ホームページを作ってくれ」 「可愛くデザインしてくれ」 「計算をしてくれ」 「5億円欲しい」 などと人間がコンピュータに頼み、それをコンピュータが理解して実行してくれればよいのですが、残念ながらそれはロシア人が日本人にロシア語でなにか頼むのと似たような結果となります…ロシア語を理解する日本人が僕の知り合いには結構いて、あまり適切なたとえとはなりませんが。

たとえばコンピュータが理解する言語は下記のような見た目となります。
ちなみにコンピュータにも人間のように 「日本人」 「韓国人」 「イギリス人」 のような種類があって、下記はいわば 「AMD64 国出身の AMD64 人のコンピュータさん」(正直自分でもなにを言っているかわからなくなってきたし、そんな国も人種もありませんが、たとえです)なら理解できる謎言語、となります。

b8 0f 00 00 00
ba 08 00 00 00
01 d0
c3

上がなに書いてあるかわかりました?
わかったなら人間引退です。あなたはたぶんコンピュータです。

…で上みたいな謎言語(というか我々人間にはそもそも上が言語なのかすらよくわからないと思います)を書かないとコンピュータさんは理解してくれないわけです…。
…しかもコンピュータさんの種類は AMD64 人だけではありません。他にも MIPS 人や PowerPC 人など、いろいろいます。
そしてそのそれぞれに独自の謎言語様式があるわけです…。
これでは人間がコンピュータと会話するのは絶望的に見えます。

そこで C 言語などの出番です!
さっき紹介した謎言語は C 言語では以下のように書くことができます。

int a = 15;
int b = 8;
a = a + b;
return a;

※ 実は厳密にはさっきの謎言語の直訳とはなっていないのですが許してほしい…。

どうでしょうか。上の C 言語で書かれたコードならかろうじてなんとなく読めるのではないですか?
そして上のコードはやがてコンパイラさんという超天才によってコンピュータが読める例の謎言語に翻訳され、コンピュータが意味を理解し実行してくれるようになります!

これが…

int a = 15;
int b = 8;
a = a + b;
return a;

コンパイラさんという超天才の翻訳によりこんな感じに翻訳してくれ…

b8 0f 00 00 00
ba 08 00 00 00
01 d0
c3

やっとコンピュータに人間の思いが伝わる!!!

上のプロセスはたとえば日本人が翻訳機を使って日本語をドイツ語に翻訳しようとするとき、日本語をそのまま翻訳機に打ち込んでも翻訳の精度が低すぎて話にならないから、精度を上げるためにいったん日本語を英語にしてから、その英語を翻訳機に打ち込んでドイツ語にする、みたいな話に似てます…似てませんかね…?

人間 - C言語 - コンパイラ(超天才翻訳者) - コンピュータの謎言語
日本人 - 英語 - 翻訳機 - ドイツ語

そうです。つまり C 言語は人間が理解できる言語とコンピュータが理解できる謎言語の中間地点のような役割を果たしているのです(めっちゃ適当)(このへんほんと適当なのであまり真に受けないほうがいいかも)。

そしてコードを書くとは、人間が理解できる言語とコンピュータが理解できる言語の中間地点としての C 言語などをがんばって記述し、それを超天才翻訳者であるコンパイラさんに渡し、コンピュータ用に翻訳してもらって、何かをコンピュータに実行してもらう一連の行為を内包するのです…たぶんね。

※ まあコンパイラさんだけでなくインタプリタさんという超天才もいるんだけどここでは割愛。

ディスアセンブルするとはどういうことかを考えます


ディスアセンブルするとは「あるプログラムがどのような仕組みで動いているか知りたくて知りたくてたまらないが、中身を見てみても例のコンピュータにしか理解できない謎言語で書かれており、何がどうなっているかさっぱりわからない」、あるいは「コンピュータウイルスに遭遇してしまい、挙動や仕組みを究明しなければいけなくなったが、当然コンピュータウイルスも例の謎言語で書かれているので、中身を見ても何言ってるか皆目わからない」などの野望や需要が生じた際に、謎言語を少しでも人間がわかりそうな感じの見た目の言語に翻訳する行為です。

ディスアセンブルの成果物として最終的に出てくるものは、下記のような見た目になります。

ディスアセンブル前

b8 0f 00 00 00
ba 08 00 00 00
01 d0
c3

ディスアセンブル後
mov eax, 0xf
mov edx, 8
add eax, edx
ret

...いや、わかります。なにを言いたいかはだいたいわかります。「下のでも(ディスアセンブルしたやつでも)まだまだなに言ってるか人間には全然わからない」ですよね?

いや、でもこれでもまあがんばったほうなんですよ。だってさっきの16進数しか並んでない超よくわからない解読自体いくら時間かけても無理そうな謎言語が、 「解読はできそう(まあだけど果てしなくめんどくさそう)」 な言語っぽい何かに変わったんですから。
少なくとも下のはがんばれば解読できそうでしょう? 「mov」 は 「move」 っぽいし、 「add」 はたぶんそのまんまだし、 「ret」 もたぶん 「return」 とかじゃないですか。まあまったく読めないよりはましでしょ...。

…みたいなことをするためのツールが今回いろいろいじって遊ぼうと思っている radare2 であり、ディスアセンブルされた内容を付加情報まで含めてもっとわかりやすく表示できたり、人間にとってより読みやすいようにもっと賢く翻訳してくれたり、いろいろできます。コンピュータの気持ちをもっと知ろう!みたいな、そんなツールです。たぶん。

r2_main


decompiler_r2


…まあいいや今回はこのくらいにして、次回以降は実際に手を動かして C 言語でプログラムを書いてみたり、それをコンパイラさんに頼み込んでコンピュータが理解できる謎言語に翻訳してもらったり、謎言語に翻訳されたプログラムをさきほどの radare2 を用いてディスアセンブルして中身を見てみたりして遊んでみようかと思います!!!

繰り返しとはなりますが、上記の内容に関する間違いやご質問などは遠慮なく Twitterツイキャス までよろしくお願いいたします…。